2017-04-18 202 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