2015-11-05 89 views
5

最近我已經做了2個實驗:爲什麼在dict中的值總是在Python中改變了?

(1):

>>> a = dict(zip([1,2,3],[4]*3)) 
>>> a 
{1: 4, 2: 4, 3: 4} 

>>> a[1] = 111  
>>> a 
{1: 111, 2: 4, 3: 4} 

(2):

>>> a = dict(zip([1,2,3],[{'a':True,'b':True}]*3)) 
>>> a 
{1: {'a': True, 'b': True}, 
2: {'a': True, 'b': True}, 
3: {'a': True, 'b': True}} 

>>> a[1]['a']=False # Here I changed the value of a[1]['a'] from True to False  
>>> a 
{1: {'a': False, 'b': True}, 
2: {'a': False, 'b': True}, 
3: {'a': False, 'b': True}}  #all 'a' value changed to False. 

爲什麼(2)發生在這個問題呢?爲什麼(1)沒有這個問題?

回答

7

簡短回答:因爲dict對象是可變的,並且int對象是不可變的。

詳情:

[{'a': True, 'b': True}] * 3

隨着

>>> l = [{}] * 3 

您創建一個包含引用同一個對象3次名單。

>>> id(l[0]) 
139685186829320 
>>> id(l[1]) 
139685186829320 
>>> id(l[2]) 
139685186829320 

所以,當你改變其中之一,你改變他們全部(在可變對象的情況下)。

如果你想不同的字典列表,你可以做到這一點:

>>> l = [{} for x in range(3)] 
>>> id(l[0]) 
139685161766216 
>>> id(l[1]) 
139685161766536 
>>> id(l[2]) 
139685161766600 

在你的情況應該是這樣的:

a = dict(zip([1, 2, 3], [{'a': True, 'b': True} for i in range(3)])) 

有了不可改變的對象是不同的

您無法更改不可變對象。任何看起來像你改變不可變對象的地方,都會創建一個新的對象。

所以,當你嘗試改變內部列表不可變對象,將創建一個新的對象:

>>> l = [1] * 3 

>>> id(l[0]) 
139685185487008 
>>> id(l[1]) 
139685185487008 
>>> id(l[2]) 
139685185487008 

>>> l[0] = 2 

>>> id(l[0]) 
139685185487040 # new object created instead of old object being modified 
>>> id(l[1]) 
139685185487008 
>>> id(l[2]) 
139685185487008 
0

如果使用列表理解(更換ZIP)或爲()循環,你不會使用相同的對象3次

a = {ctr:{'a':True,'b':True} for ctr in range(1, 4)} 
print a 
a[1]['a']=False 
print a 
相關問題