2012-07-16 54 views
59

我以編程方式創建列表字典的嘗試未能讓我單獨尋址字典鍵。每當我創建列表字典並嘗試追加到一個密鑰時,它們都會被更新。這裏是一個非常簡單的測試案例:如何在Python中初始化空列表的字典?

data = {} 
data = data.fromkeys(range(2),[]) 
data[1].append('hello') 
print data 

實際結果:{0: ['hello'], 1: ['hello']}

預期結果:{0: [], 1: ['hello']}

這裏是什麼工作

data = {0:[],1:[]} 
data[1].append('hello') 
print data 

實際和預期成果:{0: [], 1: ['hello']}

爲什麼fromkeys方法不能按預期方式工作?

回答

70

傳遞[]作爲第二個參數dict.fromkeys()給出了一個相當無用的結果 - 在字典中的所有值將是相同列表對象。

在Python 2.7或以上,你可以改用一個dicitonary理解:

data = {k: [] for k in range(2)} 

在較早版本的Python,您可以使用

data = dict((k, []) for k in range(2)) 
+1

那麼這是相當不直觀的行爲,任何想法爲什麼同一個對象用於所有鍵? – Bar 2016-04-13 19:05:21

+2

@Bar因爲除了Python語言的語義之外,沒有別的功能可以做。你傳遞一個單獨的對象作爲所有鍵的值,這樣所有鍵都使用單個對象。''fromkeys()'方法接受一個工廠函數會更好,所以我們可以將'list'作爲一個函數傳入,並且每個創建的密鑰都會調用一次函數,但這不是實際的API 'dict.fromkeys()'。 – 2016-04-13 20:30:22

42

使用defaultdict代替:

from collections import defaultdict 
data = defaultdict(list) 
data[1].append('hello') 

這樣你就不必初始化所有你想提前使用列表中的鑰匙。

什麼是你的榜樣情況是,你使用一個(可變)名單:

alist = [1] 
data = dict.fromkeys(range(2), alist) 
alist.append(2) 
print data 

將輸出{0: [1, 2], 1: [1, 2]}

+2

在我的情況下,我需要事先初始化所有的鍵,以便其餘的程序邏輯可以按預期工作,但這將是一個否則的好解決方案謝謝。 – 2012-07-16 18:06:18

6

您正在使用對單個列表的引用來填充字典,因此當您更新它時,更新會反映在所有引用中。改爲嘗試詞典理解。見 Create a dictionary with list comprehension in Python

d = {k : v for k in blah blah blah} 
+0

初始化字典值的重要建議...謝謝cobie!我擴展了您的示例以重置現有字典中的值,d。我這樣做如下: d = {k:0 for k in d} – John 2016-08-21 14:29:17

-3

您可以使用此:

data[:1] = ['hello'] 
+2

OP可能有助於解釋*爲什麼這是有效的。最初的問題張貼爲什麼它沒有按預期工作。 – 2017-06-15 18:05:47

+0

@ william.taylor.09它有點顯而易見,爲什麼這個工程,不是嗎? – 2017-06-15 18:24:46

+0

OP是(被)詢問「爲什麼fromkeys方法不能按預期工作?」 – 2017-06-15 18:29:57