Defaultdict ?

是否有一种方法可以有defaultdict(defaultdict(int))来使下面的代码工作?

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()
131987 次浏览

是的,像这样:

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())参数的返回值。

defaultdict构造函数的形参是构建新元素时将调用的函数。我们用一个!

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

从Python 2.7开始,有使用计数器甚至是更好的解决方案:

>>> 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)]

有关更多信息,请参阅集合-容器数据类型Python文档-集合

我发现使用partial更加优雅:

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

当然,这和是一样的。

其他人已经正确回答了你的问题,如何让以下工作:

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

这种方法的优点是它很简单,可以很容易地扩展。如果你需要一个三层深的映射,只需为键使用一个三项的元组。

作为参考,可以通过以下方式实现泛型嵌套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()

深度定义了在使用default_factory中定义的类型之前嵌套字典的数量。 例如:< / p >

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

以前的回答已经讨论了如何创建一个两层或n层defaultdict。在某些情况下,你想要无穷大:

def ddict():
return defaultdict(ddict)

用法:

>>> d = ddict()
>>> d[1]['a'][True] = 0.5
>>> d[1]['b'] = 3
>>> import pprint; pprint.pprint(d)
defaultdict(<function ddict at 0x7fcac68bf048>,
{1: defaultdict(<function ddict at 0x7fcac68bf048>,
{'a': defaultdict(<function ddict at 0x7fcac68bf048>,
{True: 0.5}),
'b': 3})})