Python 中的嵌套字典:分配键,但保留子结构

Nested dictionary in Python: Assigning keys, BUT keeping sub structure

我正在使用 Python 3.5,但在为字典键赋值时遇到问题。我的字典结构如下所示:

dict_var = {'file':
               {'index':
                    {'flag':
                         {'flag_key': 'False'},
                     'attr':
                         {'attr_key': 'attr_val'},
                     'path':
                         {'path_key': 'path_val'},
                     }
                }
            }

我得到 KeyError: 1,如果我像这样更改嵌套键 'index'

dict_var['file']['1']['flag'] = 'some value'
dict_var['file']['2']['flag'] = 'some value'
dict_var['file']['3']['flag'] = 'some value'
dict_var['file']['4']['flag'] = 'some value'

或者如果我尝试更改嵌套键 'flag':

dict_var['file']['index']['flag_2']['flag_key'] = 'some value'

有没有办法为嵌套键分配一个新名称,但保留以下子键和值的结构,就像我的例子一样? 我希望有人能帮助我。非常感谢和最诚挚的问候

您可以简单地将值转移到新键,然后删除旧键。例如:

dict_var['file']['1'] = dict_var['file']['index']
del dict_var['file']['index']

您可以使用嵌套 defaultdict,像这样:

from collections import defaultdict

ndefaultdict = lambda:defaultdict(ndefaultdict)

dict_var = ndefaultdict()
dict_var['file']['1']['flag'] = 'some value'
dict_var['file']['2']['flag'] = 'some value'
dict_var['file']['3']['flag'] = 'some value'
dict_var['file']['4']['flag'] = 'some value'

然后您可以编写一个简单的循环,将信息从您的原始字典传输到嵌套字典中。 示例解决方案:

from collections import defaultdict

def ndefaultdict(orig_dict):
    l = lambda: defaultdict(l)
    out = l()

    def n_helper(orig_dict, nesteddict):
        for k, v in orig_dict.items():
            if isinstance(v, dict):
                n_helper(v, nesteddict[k])
            else:
                nesteddict[k] = v
        return nesteddict

    return n_helper(orig_dict, out)

# dict_var is the original dictionary from the OP.
new_dict = n_defaultdict(dict_var)
new_dict['foo']['bar']['baz'] = 'It works!!'

print( new_dict['file']['index']['attr']['attr_key']) # attr_val

编辑:

查看this SO thread,我发现了另外两个优雅的解决方案:

  1. 来自用户 Vincent

使用 defaultdict 的简短解决方案

from collections import defaultdict

def superdict(arg=()):
    update = lambda obj, arg: obj.update(arg) or obj
    return update(defaultdict(superdict), arg)

>>> d = {"a":1}
>>> sd = superdict(d)
>>> sd["b"]["c"] = 2
  1. 来自用户 Dvd Avins

使用自定义 NestedDict class.

>>> class NestedDict(dict):
...     def __getitem__(self, key):
...         if key in self: return self.get(key)
...         return self.setdefault(key, NestedDict())


>>> eggs = NestedDict()
>>> eggs[1][2][3][4][5]
{}
>>> eggs
{1: {2: {3: {4: {5: {}}}}}}