Python添加/更新任意深度的dict元素

neh*_*iah 2 python dictionary

有这样的字典

my_pets = {
    'Rudolf': {
        'animal': 'cat', 
        'legs': 4
    }
}
Run Code Online (Sandbox Code Playgroud)

达到低于同等水平的较干净方法是什么?

my_pets['Rudolf']['legs']['front-right']['injured'] = True
my_pets['Rudolf']['legs']['front-left']['injured'] = False
Run Code Online (Sandbox Code Playgroud)

它应该更新为

my_pets = {
    'Rudolf': {
        'animal': 'cat', 
        'legs': {
            'front-right': {'injured':True},
            'front-left': {'injured':False}
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

jme*_*jme 5

您可以创建一个“无限”的 defaultdict,如下所示:

from collections import defaultdict

def infinidict():
    return defaultdict(infinidict)
Run Code Online (Sandbox Code Playgroud)

然后写:

>>> my_pets = infinidict()
>>> my_pets['Rudolf']['animal'] = 'cat'
>>> my_pets['Rudolf']['weight'] = 3
>>> my_pets['Rudolf']['legs']['front-right']['injured'] = True
>>> my_pets
defaultdict(<function __main__.infinidict>,
            {'Rudolf': defaultdict(<function __main__.infinidict>,
                         {'animal': 'cat',
                          'legs': defaultdict(<function __main__.infinidict>,
                                      {'front-right': defaultdict(<function __main__.infinidict>,
                                                   {'injured': True})}),
                          'weight': 3})})
Run Code Online (Sandbox Code Playgroud)

输出看起来很乱,但my_pets可以在dict需要a 的任何地方使用。


Igo*_*ush 5

下面是一个字典子类,它对任意深度的键丢失都很宽容:

class freedict(dict):
    # called when trying to read a missing key
    def __missing__(self, key):
        self[key] = freedict()
        return self[key]

    # called during attribute access
    # note that this invokes __missing__ above
    def __getattr__(self, key):
        return self[key]

    # called during attribute assignment
    def __setattr__(self, key, value):
        self[key] = value
Run Code Online (Sandbox Code Playgroud)

可以这样使用(对键的属性访问是个人喜好):

d = freedict()
d['one']['two']['three'] = 1
d.one.two.three = 2
Run Code Online (Sandbox Code Playgroud)