递归访问字典和修改

ezd*_*ena 2 python dictionary

我有以下字典:

my_dict = {'key1': {'key2': {'foo': 'bar'} } }
Run Code Online (Sandbox Code Playgroud)

我想在key1-> key2-> key3附加一个条目,其值为'blah',产生:

my_dict = {'key1': {'key2': {'foo': 'bar', 'key3': 'blah'} } }
Run Code Online (Sandbox Code Playgroud)

我正在寻找一个独立于键数的通用解决方案,即key1-> key2-> key3-> key4-> key5也应该工作,即使key3向下的键不存在.所以我得到:

my_dict = {'key1': {'key2': {'foo': 'bar', 'key3': {'key4': {'key5': 'blah'} } } } }
Run Code Online (Sandbox Code Playgroud)

提前致谢.

Mar*_*ers 12

您可以使用该reduce()函数遍历一系列嵌套字典:

def get_nested(d, path):
    return reduce(dict.__getitem__, path, d)
Run Code Online (Sandbox Code Playgroud)

演示:

>>> def get_nested(d, path):
...     return reduce(dict.__getitem__, path, d)
... 
>>> my_dict = {'key1': {'key2': {'foo': 'bar', 'key3': {'key4': {'key5': 'blah'}}}}}
>>> get_nested(my_dict, ('key1', 'key2', 'key3', 'key4', 'key5'))
'blah'
Run Code Online (Sandbox Code Playgroud)

当密钥不存在时,此版本抛出异常:

>>> get_nested(my_dict, ('key1', 'nonesuch'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in get_nested
KeyError: 'nonesuch'
Run Code Online (Sandbox Code Playgroud)

但你可以替换dict.__getitem__lambda d, k: d.setdefault(k, {})拥有它创建空字典,而不是:

def get_nested_default(d, path):
    return reduce(lambda d, k: d.setdefault(k, {}), path, d)
Run Code Online (Sandbox Code Playgroud)

演示:

>>> def get_nested_default(d, path):
...     return reduce(lambda d, k: d.setdefault(k, {}), path, d)
... 
>>> get_nested_default(my_dict, ('key1', 'nonesuch'))
{}
>>> my_dict
{'key1': {'key2': {'key3': {'key4': {'key5': 'blah'}}, 'foo': 'bar'}, 'nonesuch': {}}}
Run Code Online (Sandbox Code Playgroud)

要在给定路径上设置值,遍历除最后一个键之外的所有键,然后在常规字典赋值中使用最终键:

def set_nested(d, path, value):
    get_nested_default(d, path[:-1])[path[-1]] = value
Run Code Online (Sandbox Code Playgroud)

这使用该get_nested_default()函数根据需要添加空字典:

>>> def set_nested(d, path, value):
...     get_nested_default(d, path[:-1])[path[-1]] = value
... 
>>> my_dict = {'key1': {'key2': {'foo': 'bar'}}}
>>> set_nested(my_dict, ('key1', 'key2', 'key3', 'key4', 'key5'), 'blah')
>>> my_dict
{'key1': {'key2': {'key3': {'key4': {'key5': 'blah'}}, 'foo': 'bar'}}}
Run Code Online (Sandbox Code Playgroud)