Python中的多层'collection.defaultdict'使用方法

199 投票
6 回答
97488 浏览
提问于 2025-04-15 21:22

感谢一些在StackOverflow上很棒的人,我发现了collections.defaultdict的很多好处,特别是在可读性和速度方面。我已经成功地使用了它。

现在我想实现三层字典,前两层使用defaultdict,最底层使用int。但我找不到合适的方法来做到这一点。这是我的尝试:

from collections import defaultdict
d = defaultdict(defaultdict)
a = [("key1", {"a1":22, "a2":33}),
     ("key2", {"a1":32, "a2":55}),
     ("key3", {"a1":43, "a2":44})]
for i in a:
    d[i[0]] = i[1]

现在这个可以正常工作,但接下来这个我想要的效果却不行:

d["key4"]["a1"] + 1

我怀疑我应该在某个地方声明第二层的defaultdict是类型int,但我找不到在哪里或者怎么做。

我使用defaultdict的原因是为了避免每次新建一个键时都要初始化字典。

有没有更优雅的建议呢?

谢谢大家,Python爱好者们!

6 个回答

14

可以看看nosklo的回答,里面有一个更通用的解决方案,链接在这里

class AutoVivification(dict):
    """Implementation of perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            value = self[item] = type(self)()
            return value

测试:

a = AutoVivification()

a[1][2][3] = 4
a[1][3][3] = 5
a[1][2]['test'] = 6

print a

输出:

{1: {2: {'test': 6, 3: 4}, 3: {3: 5}}}
36

另一种方法来创建可以被保存的嵌套默认字典,是使用部分对象,而不是用lambda表达式:

from functools import partial
...
d = defaultdict(partial(defaultdict, int))

这样做是可行的,因为defaultdict类在模块级别是可以全局访问的:

"你不能保存一个部分对象,除非它所包装的函数(在这个例子中是类)是全局可访问的……通过它的 __name__ (在它的 __module__ 中)" -- 保存包装的部分函数

390

使用:

from collections import defaultdict
d = defaultdict(lambda: defaultdict(int))

这样做会在每次访问字典 d 中的新键时,自动创建一个新的 defaultdict(int)

撰写回答