Python添加/更新任意深度的dict元素 [英] Python adding/updating dict element of any depth

查看:431
本文介绍了Python添加/更新任意深度的dict元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

具有这样的格言

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

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

What is the cleaner way of achieving below equivalent?

my_pets['Rudolf']['legs']['front-right']['injured'] = True
my_pets['Rudolf']['legs']['front-left']['injured'] = False

它应该更新为

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

推荐答案

这是一次非常有趣且非常实际的情况. 每种解决方案都有很多解决方案,可以解决某些问题,并且错过了一些边缘方案.

This is a very interesting and a very practical situation once can encounter. There are numerous implementation each solves certain things and miss out few edge scenarios.

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

Possible solutions and varying answer can be found in these titles.

实现嵌套字典的最佳方法是什么?

在Python中初始化dict的最佳方法是什么?

设置嵌套的字典值并创建中间键

此外,关于自动生存"的要求也找到了许多要点和博客,包括维基百科的存在.

Also, there numerous gists and blogs are found on this requirement 'autovivification', including a wikipedia presence.

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

尽管边缘情况仍然存在问题,但上述实现很方便.在撰写本文时,还没有一种实现能够很好​​地处理是否存在原始的坐骑和阻挡之巢.

While the above implementation are handy once edge case could be still problematic. At the time of this writing, no implementation has handled well whether there is a primitive sitting and blocking the nest.

这里是在StackOverflow中回答此问题和相关问题的3种主要方法.

Here are the 3 mains ways this question and related questions are answered here in StackOverflow.

  • 编写一个辅助方法,该方法接受字典,值和嵌套键列表 与普通的dict对象一起使用时效果很好,但是缺少通常的方括号语法,

  • Write a helper method, that accepts dictionary, value and list of nested keys Works well with plain dict objects, but lacks the usual square bracket syntax,

使用Defaultdict并编写自定义类,从根本上讲,这是可行的,因为默认dict为缺少的键提供了{} 语法很棒,但仅适用于使用自定义类创建的对象.

Use Defaultdict and write custom class, Fundamentally this works since default dict supplies {} for missing keys Great syntax, but works only for the objects that were created using the custom class.

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

Use tuples to store and retrieve (https://stackoverflow.com/a/651930/968442) The Worst idea of all, Not even should be claimed as solution, Here is why

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

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

可以正常工作,但是当您访问mydict['foo', 'bar']时,期望值将是{'baz':1},而不是KeyError 这基本上破坏了可迭代&的想法.嵌套结构

Will work fine, But when you access mydict['foo', 'bar'] the expectation will be {'baz':1}, not a KeyError This basically destroys the idea of iterable & nested structure

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

Of the three approaches, my bet goes to option 1. By writing a tiny helper method the edge cases can be resolved pragmatically, here is my implementation.

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]

现在

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

将产生

{'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'}}

这篇关于Python添加/更新任意深度的dict元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆