Python:字典字典更新数据所有数据不仅仅是指定的数据

时间:2014-04-16 15:22:15

标签: python dictionary

我在使用字典词典方面遇到了问题,可以通过以下代码进行描述:

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"]会更新?我该如何解决这个问题?

提前致谢: - )

尼克

2 个答案:

答案 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在需要按值复制整个对象时更好。