有没有办法让defaultdict也成为defaultdict的默认值?(即无限级递归defaultdict?)
我希望能够做到:
x = defaultdict(...stuff...)
x[0][1][0]
{}
所以,我可以做x = defaultdict(defaultdict)但这只是第二层:
x[0]
{}
x[0][0]
KeyError: 0
有些食谱可以做到这一点。但是仅仅使用普通的defaultdict参数就可以做到吗?
注意,这是在询问如何做一个无限级递归defaultdict,所以它与Python不同:defaultdict of defaultdict?,这是如何做一个两级defaultdict。
我可能最终会使用串模式,但当我意识到我不知道如何做时,它让我感兴趣。
这里有一个类似于@Stanislav的答案的解决方案,适用于多处理,也允许终止嵌套:
from collections import defaultdict
from functools import partial
class NestedDD(defaultdict):
def __init__(self, n, *args, **kwargs):
self.n = n
factory = partial(build_nested_dd, n=n - 1) if n > 1 else int
super().__init__(factory, *args, **kwargs)
def __repr__(self):
return repr(dict(self))
def build_nested_dd(n):
return NestedDD(n)
我基于安德鲁的回答。
如果你想从json或现有的dict中加载数据到nester defaultdict中,请看这个例子:
def nested_defaultdict(existing=None, **kwargs):
if existing is None:
existing = {}
if not isinstance(existing, dict):
return existing
existing = {key: nested_defaultdict(val) for key, val in existing.items()}
return defaultdict(nested_defaultdict, existing, **kwargs)
https://gist.github.com/nucklehead/2d29628bb49115f3c30e78c071207775
下面是一个函数,用于嵌套的任意深度的任意基defaultdict。
(cross post from Can't pickle defaultdict)
def wrap_defaultdict(instance, times=1):
"""Wrap an instance an arbitrary number of `times` to create nested defaultdict.
Parameters
----------
instance - list, dict, int, collections.Counter
times - the number of nested keys above `instance`; if `times=3` dd[one][two][three] = instance
Notes
-----
using `x.copy` allows pickling (loading to ipyparallel cluster or pkldump)
- thanks https://stackoverflow.com/questions/16439301/cant-pickle-defaultdict
"""
from collections import defaultdict
def _dd(x):
return defaultdict(x.copy)
dd = defaultdict(instance)
for i in range(times-1):
dd = _dd(dd)
return dd