2011-02-17 65 views
215

有沒有辦法讓defaultdict(defaultdict(int))爲了使下面的代碼工作?Python:defaultdict的defaultdict?

for x in stuff: 
    d[x.a][x.b] += x.c_int 

d需要建立臨時,取決於x.ax.b元素。

我可以使用:

for x in stuff: 
    d[x.a,x.b] += x.c_int 

但後來我將無法使用:

d.keys() 
d[x.a].keys() 
+3

看到類似的問題[在Python中實現嵌套字典的最佳方式是什麼?](http://stackoverflow.com/questions/635483/what-is-the-best-way-to-implement-nested-字典式的Python)。維基百科關於[_Autovivification_]的文章中還有一些可能有用的信息(https://en.wikipedia.org/wiki/Autovivification#Python)。 – martineau 2014-01-20 20:08:04

回答

383

是這樣的:

defaultdict(lambda: defaultdict(int)) 

一個defaultdict的參數(在這種情況下是lambda: defaultdict(int))將在您嘗試訪問不存在的密鑰時調用。它的返回值將被設置爲該鍵的新值,這意味着在我們的情況下,d[Key_doesnt_exist]的值將是defaultdict(int)

如果您試圖從最後一個defaultdict訪問密鑰,即d[Key_doesnt_exist][Key_doesnt_exist],它將返回0,即最後一個defaultdict的參數的返回值,即int()

+6

它很棒!你能解釋一下這個語法背後的理由嗎? – Jonathan 2011-10-12 08:25:59

+31

@Jonathan:是的,當你嘗試訪問一個不存在的鍵並且它的返回值將會被調用時,會調用defaultdict的參數(在本例中爲`lambda:defaultdict(int)`)被設置爲這個鍵的新值,這意味着在我們的例子中`d [Key_dont_exist]`的值將是`defaultdict(int)`,並且如果你嘗試訪問最後一個defaultdict的一個鍵,即`d [Key_dont_exist] [Key_dont_exist]`它將返回0,它是最後一個``defaultdict``的參數的返回值,即`int()`,希望這會有幫助。 – mouad 2011-10-12 14:25:08

+22

`defaultdict`的參數應該是一個函數。 `defaultdict(int)`是一個字典,而`lambda:defaultdict(int)`是返回字典的函數。 – has2k1 2012-09-22 04:45:52

40

defaultdict構造函數的參數是爲構建新元素而調用的函數。所以讓我們使用lambda!

>>> from collections import defaultdict 
>>> d = defaultdict(lambda : defaultdict(int)) 
>>> print d[0] 
defaultdict(<type 'int'>, {}) 
>>> print d[0]["x"] 
0 

因爲Python 2.7,有一個even better solution using Counter

>>> from collections import Counter 
>>> c = Counter() 
>>> c["goodbye"]+=1 
>>> c["and thank you"]=42 
>>> c["for the fish"]-=5 
>>> c 
Counter({'and thank you': 42, 'goodbye': 1, 'for the fish': -5}) 

一些附加功能

>>> c.most_common()[:2] 
[('and thank you', 42), ('goodbye', 1)] 

欲瞭解更多信息,請參閱PyMOTW - Collections - Container data typesPython Documentation - collections

23

我覺得稍微飄逸使用partial

import functools 
dd_int = functools.partial(defaultdict, int) 
defaultdict(dd_int) 

當然,這與lambda相同。

6

其他人答對你如何獲得以下工作問題:

for x in stuff: 
    d[x.a][x.b] += x.c_int 

另一種方法是使用元組鍵:

d = defaultdict(int) 
for x in stuff: 
    d[x.a,x.b] += x.c_int 
    # ^^^^^^^ tuple key 

對這種做法的好處是它很簡單,可以很容易地擴展。如果你需要三層深度的映射,只需使用三項元組作爲鍵。