我想要一个字典深度嵌套。让我们考虑“深入”。要显示我需要的5级字典,例如,foo[1][2][3][4][5]
或set
作为项目。{/ p>
正如我所看到的那样here我至少可以通过两种方式实现这一目标:
list
或
from collections import defaultdict
foo = defaultdict(lambda: defaultdict(lambda:defaultdict(lambda: defaultdict(lambda: defaultdict(set)))))
然后在两种情况下我都可以from functools import partial
foo = defaultdict(partial(defaultdict, partial(defaultdict, partial(defaultdict, partial(defaultdict, set)))))
但我一直在寻找一种不那么繁琐的方法来实现这一目标,并找到了两种方法。第一个也提供与上述解决方案相同的地方:
foo[1][2][3][4][5].add(1)
和第二个等价物在此处作为answer在自动回复问题中找到。
class NestedDict(dict):
def __getitem__(self, key):
if key in self: return self.get(key)
return self.setdefault(key, NestedDict())
我喜欢最后两种方法,但我不知道如何更改它们以生成不是dict的特定类型的嵌套字典,例如,class NestedDict(dict):
"""Implementation of perl's autovivification feature."""
def __getitem__(self, item):
try:
print "__getitem__: %s" % item
return dict.__getitem__(self, item)
except KeyError:
value = self[item] = type(self)()
print "value: %s" % value
return value
或set
已完成与list
。
提前感谢任何建议,评论或更正。
答案 0 :(得分:1)
这种方法类似于你的第一个例子,除了你可以指定任何你想要的深度,而无需大量输入。
from collections import defaultdict
def nested_default_dict(num_keys, init_func):
if num_keys == 1:
return defaultdict(init_func)
else:
return defaultdict(lambda: nested_default_dict(num_keys-1, init_func))
foo = nested_default_dict(5, set)
foo[1][2][3][4][5].add("Hello World")
foo[1][2][3][4][5].add("Lorem Ipsum")
foo[1][2][3][4][5].add("Dolor sit amet")
print foo[1][2][3][4][5]
bar = nested_default_dict(3, list)
bar[4][8][15].append(16)
bar[4][8][15].append(23)
bar[4][8][15].append(42)
print bar[4][8][15]
结果:
set(['Dolor sit amet', 'Lorem Ipsum', 'Hello World'])
[16, 23, 42]
一个缺点是当你打印它们时,它们看起来不太漂亮:
>>>print foo
defaultdict(<function <lambda> at 0x0000000001FA8A58>, {1: defaultdict(<function <lambda> at 0x0000000001FAB198>, {2: defaultdict(<function <lambda> at 0x0000000001FAB208>, {3: defaultdict(<function <lambda> at 0x0000000001FAB278>, {4: defaultdict(<type 'set'>, {5: set(['Dolor sit amet', 'Lorem Ipsum', 'Hello World'])})})})})})
答案 1 :(得分:1)
这是一个自动复制程序,它不需要您设置默认工厂的级别。当您获得DefaultHasher中不存在的属性时,它会将自身更改为默认工厂的实例:
class DefaultHasher(dict):
def __init__(self, default_factory, change_self=None):
self.default_factory = default_factory
self.change_self = change_self
def change(self, key):
def _change():
x = self.default_factory()
self[key] = x
return x
return _change
def __missing__(self, key):
self[key] = DefaultHasher(self.default_factory,
self.change(key))
return self[key]
def __getattr__(self, name):
result = self.change_self()
return getattr(result, name)
foo = DefaultHasher(set)
foo[1][2][3][4][5].add(1)
print(foo)
# {1: {2: {3: {4: {5: set([1])}}}}}
foo[1][2][3].add(20)
print(foo)
# {1: {2: {3: set([20])}}}
foo[1][3] = foo[1][2]
print(foo)
# {1: {2: {3: set([20])}, 3: {3: set([20])}}}
foo[1][2].add(30)
print(foo)
# {1: {2: set([30]), 3: {3: set([20])}}}