深度嵌套Python字典

9

我有一个保存的Python字典键列表:

['level_one', 'level_two', 'test']

这些是字典的键:

mydict = {
    'level_one' : {
        'level_two' : {
            'test' : "Hello World"
        }
    }
}

通常我可以这样设置test关键字: mydict['level_one']['level_two']['test'] = "Hello StackOverflow" 不幸的是,列表/字典是动态生成的,我不知道它有多深。有没有可能通过键列表更新字典键而不使用大括号? 我只能反映出获取字符串的功能:
def deepGet(sourceDict, *keys):
    return reduce(lambda d, k: d.get(k) if d else None, keys, sourceDict)

> deepGet(mydict, *['level_one', 'level_two', 'test'])
>> Hello World

不是重复。这是关于设置而不是获取嵌套字典的问题。


1
弹出列表的最后一项,使用您的deepGet函数并将弹出的键设置为结果字典中的值。 - Klaus D.
@KlausD。听起来不错的想法!我会试一试 :-) - RA.
2个回答

8
现在有一种方法可以动态地设置值,而不必将容器类型更改为defaultdict或其他动态创建类型:glom.assign()
下面是一个针对您的情况的使用示例:
import glom

target = {}
path = 'level_one.level_two.test'

glom.assign(target, path, 'hello world', missing=dict)
# {'level_one': {'level_two': {'test': 'hello world'}}}

请注意,我们传递了 missing=dict,告诉 glom 使用内置的 dict 构造函数创建缺失的键。您还需要 pip install glom,但它是纯 Python 代码,并且与 Python 2、3 和 PyPy 兼容。
使用 glom,您可以做更多的事情,特别是在深度获取和设置方面。我应该知道,因为(充分披露)我创造了它。这意味着,如果您发现有空缺,应该告诉我


6
我们需要一个 defaultdict,它将一直保持制造新实例的状态。
import collections

recursive_dict = lambda: collections.defaultdict(recursive_dict)

mydict = recursive_dict()

现在,你可以简化deepGet函数的实现,只需使用operator.getitem代替当前的lambda表达式。 operator.getitemlambda a, b: a[b]的"缩写"。

至于设置键值,你可以编写一个循环:

keys = ['level_one', 'level_two', 'test']
d = mydict
for key in keys[:-1]:
    d = d[key]
d[keys[-1]] = 'Hello World'

如果字典缺失,defaultdict会自动创建它们,无需先行检查。

将此转换为reduce()调用留给读者作为练习。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接