具有混合数据类型的 Python 嵌套 defaultdict

Sam*_*Rad 5 python dictionary defaultdict

那么,我如何为此创建一个 defaultdict:

{
    'branch': {
        'count': 23,
        'leaf': {
            'tag1': 30,
            'tag2': 10
        }
    },
}
Run Code Online (Sandbox Code Playgroud)

这样,我会为count,tag1tag2作为默认值得到零?我想在阅读输入时动态填充字典。当我看到一个新的时,branch我想创建一个count零字典和一个空字典作为叶子。当我得到 a 时leaf,我想用它的名字创建一个键并将值设置为零。

更新:接受 Martijn 的答案,因为它有更多的赞成票,但其他答案同样好。

Mar*_*ers 5

您不能使用 来执行此操作defaultdict,因为工厂无权访问密钥。

但是,您可以创建子类dict来创建您自己的“智能”defaultdict类。提供您自己的根据键添加值的__missing__方法:

class KeyBasedDefaultDict(dict):
    def __init__(self, default_factories, *args, **kw):
        self._default_factories = default_factories
        super(KeyBasedDefaultDict, self).__init__(*args, **kw)

    def __missing__(self, key):
        factory = self._default_factories.get(key)
        if factory is None:
            raise KeyError(key)
        new_value = factory()
        self[key] = new_value
        return new_value
Run Code Online (Sandbox Code Playgroud)

现在您可以提供自己的映射:

mapping = {'count': int, 'leaf': dict}
mapping['branch'] = lambda: KeyBasedDefaultDict(mapping)

tree = KeyBasedDefaultDict(mapping)
Run Code Online (Sandbox Code Playgroud)

演示:

>>> mapping = {'count': int, 'leaf': dict}
>>> mapping['branch'] = lambda: KeyBasedDefaultDict(mapping)
>>> tree = KeyBasedDefaultDict(mapping)
>>> tree['branch']['count'] += 23
>>> tree['branch']['leaf']['tag1'] = 30
>>> tree['branch']['leaf']['tag2'] = 10
>>> tree
{'branch': {'count': 23, 'leaf': {'tag1': 30, 'tag2': 10}}}
Run Code Online (Sandbox Code Playgroud)