Python中的多层'collection.defaultdict'使用方法
感谢一些在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)
。