在 Python 中处理深度嵌套字典的便捷方法

Posted

技术标签:

【中文标题】在 Python 中处理深度嵌套字典的便捷方法【英文标题】:Convenient way to handle deeply nested dictionary in Python 【发布时间】:2018-10-05 06:28:26 【问题描述】:

我在 python 中有一个深度嵌套的字典,占用了很多空间。有没有办法缩写像这样的东西

master_dictionary['sub_categories'][sub_cat_name]['attributes'][attribute_name]['special_type']['nested_children'][child_cat_name][color] = blue

以这个为例

nested_child_info[color] = blue

仍然让它编辑字典吗?我希望这是有道理的。

【问题讨论】:

这是设置一件事的最快方法。如果您有更多数据要设置,您可以获取最小的公分母并从那里开始工作。 【参考方案1】:
nested_child_info = master_dictionary['sub_categories'][sub_cat_name]['attributes'][attribute_name]['special_type']['nested_children'][child_cat_name]
nested_child_info[color] = blue

nested_child_info 是一个引用,因此更改其内容将更改master_dictionary 的内容。

【讨论】:

【参考方案2】:

你能做这样的事情吗?

thing = 1: 2: 3: 4: 'hello': 'world'
a = thing[1]
b = a[2]
c = b[3]
d = c[4]
print(d) # 'hello': 'world'

【讨论】:

【参考方案3】:

由于字典是可变的,这实际上会完全按照您的预期发生:

>>> test = 'outer': 'thing', 'inner': 'thing': 'im the inner thing'
>>> inner_thing = test['inner']
>>> inner_thing
'thing': 'im the inner thing'
>>> inner_thing['thing'] = 'im something new'
>>> inner_thing
'thing': 'im something new'
>>> test
'outer': 'thing', 'inner': 'thing': 'im something new'

这是因为可变对象在 python 中是通过引用传递的,而不是作为副本传递的(关于这方面的优秀文章很多,因此不再详述)。

但是,值得注意的是,您实际上可能不想更改原始 dict,因为它可能会对使用此变量的其他代码产生不良影响(这取决于您的代码库)。在这种情况下,我通常会复制需要变异的数据以避免副作用:

>>> from copy import deepcopy
>>> test = 'outer': 'thing', 'inner': 'thing': 'im the inner thing'
>>> new_test = deepcopy(test)
>>> inner_thing = test['inner']
>>> inner_thing['thing'] = 'im something new'
>>> test
'outer': 'thing', 'inner': 'thing': 'im something new'
>>> new_test
'outer': 'thing', 'inner': 'thing': 'im the inner thing'

【讨论】:

【参考方案4】:

是的,你可以。

>>> dict1 = 'foo':'bar':'baz':0
>>> dict2 = dict1['foo']['bar']
>>> dict2['baz'] = 1
>>> dict1
'foo': 'bar': 'baz': 1 # dict1 has been modified

【讨论】:

【参考方案5】:

如果你有一些“固定”键,你总是可以创建一个函数:

考虑这个例子:

d = dict(a=dict(sub_categories=dict(b=1)))

def changevalue(value, lvl1, lvl2):
    d[lvl1]['sub_categories'][lvl2] = value

changevalue(2,'a','b')

print(d)

#'a': 'sub_categories': 'b': 2

在你的情况下,你想退出:

[sub_cat_name], [attribute_name], [child_cat_name], [color] ...也许

【讨论】:

【参考方案6】:

类似于@fferri。您将始终必须在 long 列表中指定项目。使用reducegetitem 获取对最终字典的引用

from functools import reduce
from operator import getitem

d = 1:2:3:4:5

foo = 2
items = [1,foo,3]
result = d
info = reduce(getitem, items, d)


>>> info[4]
5
>>> d
1: 2: 3: 4: 5
>>> info[4] = 99
>>> d
1: 2: 3: 4: 99

我也在玩一个类,但它似乎没有很多优点 - 除了你可以自定义一个键错误异常,以便错误消息告诉你哪个键在哪个深度丢失。

class Drilldown:
    def __init__(self, d, path):
        #self.final = reduce(getitem, path, d)
        self.final = d
        for i, item in enumerate(path, 1):
            try:
                self.final = self.final[item]
            except KeyError as e:
                msg = ''.join('[]' for _ in range(i))
                msg = msg.format(*path[:i])
                msg = 'The last key in the path "" does not exist'.format(msg)
                e.args = [msg]
                raise
    def __call__(self, item):
        return self.final[item]
    def __setitem__(self, item, value):
        self.final[item] = value
    def __getitem__(self, item):
        return self.final[item]
    def __str__(self):
        return str(self.final)
    def __repr__(self):
        return repr(self.final)

>>> z = 19
>>> items = [1,2,z]
>>> q = Drilldown(d,items)
Traceback (most recent call last):
  File "<pyshell#68>", line 1, in <module>
    q = Drilldown(d,items)
  File "C:\pyProjects33\tmp.py", line 32, in __init__
    self.final = self.final[item]
KeyError: 'The last key in the path "[1][2][19]" does not exist'

>>> 
>>> #normal usage
>>> items = [1,2,3]
>>> q = Drilldown(d,items)
>>> d
1: 2: 3: 4: 5
>>> q
4: 5
>>> q(4)
5
>>> q[4]
5
>>> q[4] += 20
>>> q
4: 25
>>> d
1: 2: 3: 4: 25
>>> q['foo'] = '99'
>>> q
4: 25, 'foo': '99'
>>> d
1: 2: 3: 4: 25, 'foo': '99'
>>> 

【讨论】:

以上是关于在 Python 中处理深度嵌套字典的便捷方法的主要内容,如果未能解决你的问题,请参考以下文章

精选12个函数,它们可让 Python 数据处理更容易更便捷

如何重命名字典列表中深度嵌套的键(Python 3)?

Python字典嵌套字典排序,该怎么处理?

Python递归替换嵌套字典键中的字符?

python_jsonpath方法

在深度嵌套字典中添加所有值