defaultdict的defaultdict?

485 投票
7 回答
159450 浏览
提问于 2025-04-16 12:00

有没有办法创建一个 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()

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() 的结果。

撰写回答