2017-04-18 204 views
1

我在Python 2.7.12嵌套字典中看到了一个奇怪的行为,我不明白它为什么会发生。让说,我有这个词典:带有奇怪填充行为的python嵌套字典

list_1 = ['5', '10', '15', '30'] 
dict_1 = { i:[] for i in list_1 } 

现在我创建一个嵌套的字典是这样的:

list_2 = ['a', 'b'] 
dict_2 = { i:dict_1 for i in list_2 } 

和其他嵌套的字典是这样的:

dict_3 = { i:{j:[] for j in list_1} for i in list_2 } 

的dict_3和dict_2如果在填写之前印刷,则是相同的:

{'a': {'15': [], '10': [], '30': [], '5': []}, 'b': {'15': [], '10': [], '30': [], '5': []}} 

但是当我填写的字典,如:

dict_2['a']['5'].append(1) 
dict_3['a']['5'].append(1) 

dict_2有,我不希望有一个行为,请在 'A' 和 'B' 的灌装机构 '5':

{'a': {'15': [], '10': [], '30': [], '5': [1]}, 'b': {'15': [], '10': [], '30': [], '5': [1]}} 

dict_1在“A”,我想,仅填充元素的行为“5”:我猜测,在dict_2嵌套dict_1仅仅是一个到词典链接

{'a': {'15': [], '10': [], '30': [], '5': [1]}, 'b': {'15': [], '10': [], '30': [], '5': []}} 

,而dict_3是一个真正的嵌套字典。那是对的吗 ?无论如何,我觉得这个python dicts的使用很具误导性,如果它不是bug,为什么在python中需要这种行为?

+0

你为什么觉得这很奇怪? 'dict_2'包含两个对同一个'dict_1'的引用,而每次调用时,{}'理解都会创建一个新的字典。 – dhke

+0

@dhke它对于来自语言分配可以复制数据的人来说很陌生。 – timgeb

+0

@timgeb采取了点。 – dhke

回答

2

赋值永不复制数据。在理解中看到这项任务有点难。

dict_2 = {i:dict_1 for i in list_2} 

相当于

dict_2 = {} 
for i in list_2: 
    dict_2[i] = dict_1 # the assignments I'm talking about 

现在你必须dict_2[i]dict_1参考所有i。没有数据被复制。在内存中有一个值为{'15': [], '10': [], '30': [], '5': []}的字典,名称为dict_1,但现在也被dict_2中的所有密钥引用。 (您可以在内存中的值相同许多名称/引用。)

如果你希望你的字典的实际深层副本,使用

>>> from copy import deepcopy 
>>> dict_2 = {i:deepcopy(dict_1) for i in list_2} 
>>> dict_2['a']['5'].append(1) 
>>> dict_2 
{'a': {'10': [], '30': [], '15': [], '5': [1]}, 'b': {'10': [], '30': [], '15': [], '5': []}} 

同样的逻辑也适用于dict_3

+0

这更清晰了,我已经做了一些更多的列表和字典测试,是的,我不明白,分配实际上是引用。无论如何,它仍然有点误导因为这个: 'a = 0'; 'b = a'; 'a = 10'; 'print a'; 'print b'; 在这种情况下输出将是10和0,这意味着有一个副本时,有一个任务!我希望代码可读。 – IMP

+0

@IanMartinPostuma否,在Python分配中不要复制数据。这是真的。总是。这就是你的例子中发生的事情:你把名字'a'绑定到值'0'。然后你绑定另外一个名字,'b'在字面上与内存中的同一个对象绑定。然后你*重新命名'a'到另一个值。该操作不会影响名称“b”指向的内容。在这个过程中没有数据被复制。 – timgeb

+0

所以在我的最后一个例子中,我已经完成了同样的工作,就好像我在list_1中做了'dict_2 ['b'] = {i:[]],这样我重新绑定了'dict_2 ['b']'元素到另一个值,而不需要重新绑定'dict_2 ['a']'元素。好 !非常感谢,我会牢记它! – IMP