我在使用字典词典方面遇到了问题,可以通过以下代码进行描述:
Dic_A = {}
Dic_B = {}
Dic_A["A1"] = "1"
Dic_A["A2"] = "2"
Dic_B["AA"] = Dic_A
print "Dic_B after : " + str(Dic_B)
Dic_A["A1"] = "4"
Dic_A["A2"] = "5"
print "Dic_B before: " + str(Dic_B)
Dic_B["AB"] = Dic_A
print "Dic_B after : " + str(Dic_B)
我得到的输出是:
Dic_B after : {'AA': {'A1': '1', 'A2': '2'}}
Dic_B before: {'AA': {'A1': '4', 'A2': '5'}}
Dic_B after : {'AA': {'A1': '4', 'A2': '5'}, 'AB': {'A1': '4', 'A2': '5'}}
为什么在更新Dic_A时Dic_B [" AA"]会更新?我该如何解决这个问题?
提前致谢: - )
尼克
答案 0 :(得分:3)
为什么在更新Dic_A时Dic_B [“AA”]会更新?我该如何解决这个问题?
因为Dic_B["AA"]
Dic_A
。这就是Dic_B["AA"] = Dic_A
的含义。试试print(Dic_B["AA"] is Dic_A
。您会注意到它打印True
,因为它们实际上是同一个对象。
如果您不想存储对同一字典的两个引用,则需要创建新对象,而不是在旧对象中重新分配值。
dic_a = {} # new dictionary
dic_a['A1'] = '1'
dic_a['A2'] = '2'
dic_b['AA'] = dic_a # store dic_a in dic_b
dic_a = {} # CREATE a new dictionary and point the name dic_a to it.
dic_a['A1'] = '1'
dic_a['A2'] = '2'
dic_b['AA'] = dic_a # store the NEW dic_a in dic_b
当然,有更好的方法可以做到这一点,并且你可以采取一些措施让你的生活更轻松,就像更好地命名词典一样。例如,您可以利用dict
类型可以将字典复制到新实例的事实,因此如果您想继续重用源字典,您可以执行此操作并始终插入副本进入父词典:
# put stuff in dic_a...
dic_b['AA'] = dict(dic_a) # put a copy of dic_a into dic_b
# put different stuff in dic_a...
dic_b['AB'] = dict(dic_a) # put a copy of the altered dic_a into dic_b
答案 1 :(得分:2)
他们称之为最不惊讶的原则。开个玩笑。
这样做:
Dic_B["AA"] = Dic_A
print(Dic_B['AA'] is Dic_A)
您将在输出中看到True
。这意味着您认为按价值复制的对象是通过引用复制的,如果您在一个地方修改它,它也会在另一个地方被修改。
另请查看this question。
有解决方案:
from copy import copy
Dic_B["AA"] = copy(Dic_A)
或
from copy import deepcopy
Dic_B["AA"] = deepcopy(Dic_A)
或
Dic_B["AA"] = dict(Dic_A)
或
Dic_B["AA"] = {}
Dic_B["AA"].update(Dic_A)
所有解决方案都可以解决您的问题,但是只有第二个一个会从Dic_A
按值复制值(而不是通过引用)。例如,Dic_A
可能包含一些list
对象,只有deepcopy
会按值复制它,其他解决方案会通过引用复制它:
>>> from copy import copy, deepcopy
>>> Dic_A = {'key': ['v', 'a', 'l', 'u', 'e']}
>>> Dic_B = copy(Dic_A)
>>> Dic_B is Dic_A # Different `dict` objecst, but ...
False
>>> Dic_B['key'] is Dic_A['key'] # The same `list` object
True
>>> Dic_B = deepcopy(Dic_A)
>>> Dic_B is Dic_A # Different `dict` objects
False
>>> Dic_B['key'] is Dic_A['key'] # and `list` objects
False
所以,我认为deepcopy
在需要按值复制整个对象时更好。