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

2024-04-29 00:59:30 发布

您现在位置:Python中文网/ 问答频道 /正文

有这样的口述吗

my_pets = {
    'Rudolf': {
        'animal': 'cat', 
        'legs': 4
    }
}

达到低于同等标准的更清洁的方法是什么?在

^{pr2}$

它应该更新为

my_pets = {
    'Rudolf': {
        'animal': 'cat', 
        'legs': {
            'front-right': {'injured':True},
            'front-left': {'injured':False}
        }
    }
}

Tags: 方法righttrue标准myleftcatfront
3条回答

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

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

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

^{pr2}$

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

from collections import defaultdict

def infinidict():
    return defaultdict(infinidict)

然后写:

^{pr2}$

输出看起来很混乱,但是只要需要dict,就可以使用my_pets。在

这是一个非常有趣和非常实际的情况,曾经可以遇到。 有许多实现,每种实现都能解决某些问题,并且遗漏了一些边缘场景。在

在这些标题中可以找到可能的解决方案和不同的答案。在

^{bq}$

此外,有许多注册官和博客在这一要求'自生',包括维基百科的存在。在

http://blog.yjl.im/2013/08/autovivification-in-python.html

https://news.ycombinator.com/item?id=3881171

https://gist.github.com/hrldcpr/2012250

https://en.wikipedia.org/wiki/Autovivification

http://blogs.fluidinfo.com/terry/2012/05/26/autovivification-in-python-nested-defaultdicts-with-a-specific-final-type/

虽然上面的实现是方便的一旦边缘情况可能仍然有问题。在撰写本文时,还没有一个实现能够很好地处理是否存在原始坐和阻塞嵌套。在

这里有3个主要的方法,这个问题和相关的问题在这里StackOverflow回答。在

  • 编写一个helper方法,它接受dictionary、value和嵌套键列表 可以很好地处理普通dict对象,但缺少常用的方括号语法,

  • 使用Defaultdict并编写自定义类,因为Defaultdict为丢失的键提供{},所以基本上这是可行的 语法很棒,但只适用于使用自定义类创建的对象。

  • 使用元组存储和检索(https://stackoverflow.com/a/651930/968442) 最糟糕的想法,甚至不应该被称为解决方案,这里是为什么

    mydict = {}
    mydict['foo', 'bar', 'baz'] = 1
    print mydict['foo', 'bar', 'baz']

    可以正常工作,但是当您访问mydict['foo', 'bar']时,期望值是{'baz':1},而不是KeyError 这基本上破坏了iterable&nested structure的思想

在这三种方法中,我打赌选择1。通过编写一个小的辅助方法,可以实际地解决边缘情况,这是我的实现。在

def sattr(d, *attrs):
    # Adds "val" to dict in the hierarchy mentioned via *attrs
    for attr in attrs[:-2]:
        # If such key is not found or the value is primitive supply an empty dict
        if d.get(attr) is None or isinstance(d.get(attr), dict):
            d[attr] = {}
        d = d[attr]
    d[attrs[-2]] = attrs[-1]

现在

^{pr2}$

会产生

{'Rudolf': {'legs': 4, 'animal': 'cat'}}
{'Rudolf': {'legs': {'front-right': {'injured': True}}, 'animal': 'cat'}}
{'Rudolf': {'legs': {'front-left': {'injured': False}, 'front-right': {'injured': True}}, 'animal': 'cat'}}

相关问题 更多 >