defaultdict的defaultdict?
有没有办法创建一个 defaultdict(defaultdict(int))
,这样可以让下面的代码正常工作呢?
for x in stuff:
d[x.a][x.b] += x.c_int
d
需要根据 x.a
和 x.b
的元素动态构建。
我可以使用:
for x in stuff:
d[x.a,x.b] += x.c_int
但是那样的话,我就不能使用:
d.keys()
d[x.a].keys()
7 个回答
46
之前的回答讨论了如何创建一个两层或多层的 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})})
58
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开始,还有一个更好的解决方案,就是使用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 - 容器数据类型和Python文档 - collections
859
是这样的:
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()
的结果。