天天看點

Python:defaultdict的defaultdict?

本文翻譯自:Python: defaultdict of defaultdict?

Is there a way to have a

defaultdict(defaultdict(int))

in order to make the following code work?

有沒有一種方法使

defaultdict(defaultdict(int))

可以使以下代碼正常工作?
for x in stuff:
    d[x.a][x.b] += x.c_int
           

d

needs to be built ad-hoc, depending on

xa

and

xb

elements.

d

需要臨時建構,具體取決于

xa

xb

元素。

I could use:

我可以使用:
for x in stuff:
    d[x.a,x.b] += x.c_int
           

but then I wouldn't be able to use:

但後來我将無法使用:
d.keys()
d[x.a].keys()
           

#1樓

參考:https://stackoom.com/question/l6vY/Python-defaultdict的defaultdict

#2樓

Yes like this:

是這樣的:
defaultdict(lambda: defaultdict(int))
           

The argument of a

defaultdict

(in this case is

lambda: defaultdict(int)

) will be called when you try to access a key that doesn't exist.

當您嘗試通路不存在的鍵時,将調用

defaultdict

的參數(在本例中為

lambda: defaultdict(int)

)。

The return value of it will be set as the new value of this key, which means in our case the value of

d[Key_doesnt_exist]

will be

defaultdict(int)

.

它的傳回值将設定為該鍵的新值,這意味着在我們的示例中

d[Key_doesnt_exist]

的值将為

defaultdict(int)

If you try to access a key from this last defaultdict ie

d[Key_doesnt_exist][Key_doesnt_exist]

it will return 0, which is the return value of the argument of the last defaultdict ie

int()

.

如果您嘗試從最後一個defaultdict即

d[Key_doesnt_exist][Key_doesnt_exist]

通路密鑰,它将傳回0,這是最後一個defaultdict即

int()

的參數的傳回值。

#3樓

The parameter to the defaultdict constructor is the function which will be called for building new elements.

defaultdict構造函數的參數是用于建構新元素的函數。

So let's use a lambda !

是以,讓我們使用lambda!
>>> from collections import defaultdict
>>> d = defaultdict(lambda : defaultdict(int))
>>> print d[0]
defaultdict(<type 'int'>, {})
>>> print d[0]["x"]
0
           

Since Python 2.7, there's an even better solution using Counter :

從Python 2.7開始, 使用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})
           

Some bonus features

一些額外功能
>>> c.most_common()[:2]
[('and thank you', 42), ('goodbye', 1)]
           

For more information see PyMOTW - Collections - Container data types and Python Documentation - collections

有關更多資訊,請參見PyMOTW-集合-容器資料類型和Python文檔-集合

#4樓

I find it slightly more elegant to use

partial

:

我發現使用

partial

稍微優雅

partial

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

Of course, this is the same as a lambda.

當然,這與lambda相同。

#5樓

Others have answered correctly your question of how to get the following to work:

其他人已經正确回答了您有關如何使以下内容正常工作的問題:
for x in stuff:
    d[x.a][x.b] += x.c_int
           

An alternative would be to use tuples for keys:

一種替代方法是使用元組作為鍵:
d = defaultdict(int)
for x in stuff:
    d[x.a,x.b] += x.c_int
    # ^^^^^^^ tuple key
           

The nice thing about this approach is that it is simple and can be easily expanded.

這種方法的好處是它很簡單并且可以輕松擴充。

If you need a mapping three levels deep, just use a three item tuple for the key.

如果您需要三個層次的映射,隻需使用一個三項元組作為鍵。

#6樓

For reference, it's possible to implement a generic nested

defaultdict

factory method through:

作為參考,可以通過以下方式實作通用的嵌套

defaultdict

工廠方法:
from collections import defaultdict
from functools import partial
from itertools import repeat


def nested_defaultdict(default_factory, depth=1):
    result = partial(defaultdict, default_factory)
    for _ in repeat(None, depth - 1):
        result = partial(defaultdict, result)
    return result()
           

The depth defines the number of nested dictionary before the type defined in

default_factory

is used.

在使用

default_factory

定義的類型之前,深度定義了嵌套字典的數量。

For example:

例如:
my_dict = nested_defaultdict(list, 3)
my_dict['a']['b']['c'].append('e')