2013-10-03 72 views
4

這是我的代碼:python:爲什麼listA.append('a')影響listB?

In [8]: b=dict.fromkeys([1,2,3,4], []) 

In [9]: b[1].append(1) 

In [10]: b[2].append(2) 

In [11]: b[1] 
Out[11]: [1, 2] 

In [12]: b[2] 
Out[12]: [1, 2] 

In [13]: b 
Out[13]: {1: [1, 2], 2: [1, 2], 3: [1, 2], 4: [1, 2]} 

儘管我期望:{1:[1],2:[2],3:[],4:[]}

我想這是也許由b [X]引起的只是一個「參考」,它們都指向同一個列表。

然後我用int對象替換[]。結果讓我更加困惑:

In [15]: b=dict.fromkeys([1,2,3,4], 1) 

In [16]: b[1] += 1 

In [17]: b[2] += 1 

In [18]: b 
Out[18]: {1: 2, 2: 2, 3: 1, 4: 1} 

這個int對象1在這種情況下不是一個參照。

然後,我[ '一']代替[]:

In [19]: b=dict.fromkeys([1,2,3,4], ['a']) 

In [20]: b[1].append(1) 

In [21]: b[2].append(2) 

In [22]: b 
Out[22]: {1: ['a', 1, 2], 2: ['a', 1, 2], 3: ['a', 1, 2], 4: ['a', 1, 2]} 

現在[ 'A']是再次參考。

有人可以告訴我爲什麼,以及如何在第一種情況下獲得預期結果「{1:[1],2:[2],3:[],4:[]}」。

任何有用的建議表示讚賞。

回答

6

因爲字典中的所有值實際上都是對同一列表的引用,所以dict.fromkeys使用相同的列表對象並將其分配給每個鍵。由於list.append是就地操作,因此所有密鑰都受到影響。

>>> b = dict.fromkeys([1,2,3,4], []) 
>>> [id(x) for x in b.values()] 
[158948300, 158948300, 158948300, 158948300] 

因此,對於可變值使用字典理解:

>>> b = {k:[] for k in xrange(1, 5)} 
>>> [id(x) for x in b.values()] 
[158945580, 158948396, 158948108, 158946764] 

或者作爲@Bakuriu建議,collections.defaultdict也沒關係:

>>> from collections import defaultdict 
>>> dic = defaultdict(list) 
>>> dic[1].append(1) 
>>> dic[2].append(2) 
>>> dic 
defaultdict(<type 'list'>, {1: [1], 2: [2]}) 
>>> dic[3] 
[] 
+2

甚至更​​好:使用'defaultdict'來避免完全使用'fromkeys'。 – Bakuriu

+0

謝謝,它現在非常有意義。 – AttufliX

4

他們真的是所有引用。區別在於你如何處理參考。

當您使用賦值運算符=時,您將設置對不同對象的引用。 (+=工作原理相同)。

當您使用append時,您正在修改對象而不影響引用。由於fromkeys將多個引用返回給同一個對象,因此所有這些修改都可以同時看到。

+0

這個概念上的解釋實際上確實解決了OP的問題,+1 – iruvar

+0

謝謝,這個答案也增加了我的理解。 – AttufliX

相關問題