2013-03-20 39 views
27

這是導致我有點悲傷的...dict.fromkeys都指向同一個列表

我創建了一個字典從列表

l = ['a','b','c'] 
d = dict.fromkeys(l, [0,0]) # initializing dictionary with [0,0] as values 

d['a'] is d['b'] # returns True 

我怎樣才能讓字典中的每個值單獨列表?這可能沒有迭代所有的鍵,並將它們設置爲一個列表?我想修改一個列表而不更改所有其他列表。

回答

25

你可以使用字典理解:

>>> keys = ['a','b','c'] 
>>> value = [0, 0] 
>>> {key: list(value) for key in keys} 
    {'a': [0, 0], 'b': [0, 0], 'c': [0, 0]} 
+1

'list(value)'和'value [:]'是同一件事嗎? – Droogans 2014-04-20 01:56:54

+1

@Droogans:是的。我只是發現空白符號醜陋。 – Blender 2014-04-20 02:51:03

6

您可以使用此:

l = ['a', 'b', 'c'] 
d = dict((k, [0, 0]) for k in l) 
2
l = ['a','b','c'] 
d = dict((i, [0, 0]) for i in l) 
-4
keys = ['a','b','c'] 
value = [0, 0] 
d = dict.fromkeys(keys,value) 
print d 
# {'a':[0, 0], 'b':[0, 0], 'c':[0, 0]} 
+0

歡迎來到堆棧溢出!雖然這些規範可能會回答這個問題,但提供關於爲什麼和/或如何回答問題的附加背景將顯着提高其長期價值。請[編輯]你的答案,添加一些解釋。 – CodeMouse92 2016-04-19 19:01:15

+0

此答案無效。試試'd ['a']是d ['b']',你會發現它仍然是'真',這意味着它們都指向相同的數組。其他答案是正確的,因爲每個鍵都有一個不同的數組副本 – 2016-04-19 20:23:50

4

這答案就在這裏來解釋這種行爲對任何人對結果狼狽他們試圖實例化dictfromkeys()與可變的默認值。

考慮:

#Python 3.4.3 (default, Nov 17 2016, 01:08:31) 

# start by validating that different variables pointing to an 
# empty mutable are indeed different references. 
>>> l1 = [] 
>>> l2 = [] 
>>> id(l1) 
140150323815176 
>>> id(l2) 
140150324024968 

所以任何變化l1不會影響l2,反之亦然。 對於任何可變的目前來說都是如此,包括dict

# create a new dict from an iterable of keys 
>>> dict1 = dict.fromkeys(['a', 'b', 'c'], []) 
>>> dict1 
{'c': [], 'b': [], 'a': []} 

這可以是一個方便的功能。 這裏我們給每個鍵分配一個默認值,它也恰好是一個空列表。

# the dict has its own id. 
>>> id(dict1) 
140150327601160 

# but look at the ids of the values. 
>>> id(dict1['a']) 
140150323816328 
>>> id(dict1['b']) 
140150323816328 
>>> id(dict1['c']) 
140150323816328 

事實上,他們都使用相同的參考! 對一個人的改變是對所有人的改變,因爲他們實際上是同一個對象!

>>> dict1['a'].append('apples') 
>>> dict1 
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']} 
>>> id(dict1['a']) 
>>> 140150323816328 
>>> id(dict1['b']) 
140150323816328 
>>> id(dict1['c']) 
140150323816328 

很多,這不是什麼意圖!

現在讓我們試着將列表的顯式副本用作默認值。

>>> empty_list = [] 
>>> id(empty_list) 
140150324169864 

,現在創建的empty_list副本的字典。

>>> dict2 = dict.fromkeys(['a', 'b', 'c'], empty_list[:]) 
>>> id(dict2) 
140150323831432 
>>> id(dict2['a']) 
140150327184328 
>>> id(dict2['b']) 
140150327184328 
>>> id(dict2['c']) 
140150327184328 
>>> dict2['a'].append('apples') 
>>> dict2 
{'c': ['apples'], 'b': ['apples'], 'a': ['apples']} 

還是沒有快樂! 我聽到有人在喊,這是因爲我用了一個空的名單!

>>> not_empty_list = [0] 
>>> dict3 = dict.fromkeys(['a', 'b', 'c'], not_empty_list[:]) 
>>> dict3 
{'c': [0], 'b': [0], 'a': [0]} 
>>> dict3['a'].append('apples') 
>>> dict3 
{'c': [0, 'apples'], 'b': [0, 'apples'], 'a': [0, 'apples']} 

fromkeys()默認行爲是分配None的值。

>>> dict4 = dict.fromkeys(['a', 'b', 'c']) 
>>> dict4 
{'c': None, 'b': None, 'a': None} 
>>> id(dict4['a']) 
9901984 
>>> id(dict4['b']) 
9901984 
>>> id(dict4['c']) 
9901984 

事實上,所有的值是相同的(和唯一的!)None。 現在,讓我們通過dict以無數種方式之一進行迭代並更改值。

>>> for k, _ in dict4.items(): 
... dict4[k] = [] 

>>> dict4 
{'c': [], 'b': [], 'a': []} 

嗯。看起來和以前一樣!

>>> id(dict4['a']) 
140150318876488 
>>> id(dict4['b']) 
140150324122824 
>>> id(dict4['c']) 
140150294277576 
>>> dict4['a'].append('apples') 
>>> dict4 
>>> {'c': [], 'b': [], 'a': ['apples']} 

但他們確實不同[] s,在這種情況下,這是預期的結果。

+0

所以我們必須迭代? – user1712447 2018-01-25 02:46:51

相關問題