我可以使用键列表访问嵌套的dict吗?

Mar*_*oma 11 python dictionary python-3.x

我想以编程方式访问字典.我知道如何使用递归函数执行此操作,但有更简单的方法吗?

example = {'a': {'b': 'c'},
           '1': {'2': {'3': {'4': '5'}}}}

keys = ('a', 'b')
example[keys] = 'new'
# Now it should be
#     example = {'a': {'b': 'new'},
#                '1': {'2': {'3': {'4': '5'}}}}


keys = ('1', '2', '3', '4')
example[keys] = 'foo'
# Now it should be
#     example = {'a': {'b': 'new'},
#                '1': {'2': {'3': {'4': 'foo'}}}}


keys = ('1', '2')
example[keys] = 'bar'
# Now it should be
#     example = {'a': {'b': 'new'},
#                '1': {'2': 'bar'}}
Run Code Online (Sandbox Code Playgroud)

Oli*_*çon 5

您似乎想要做的是定义自己的字典类,以支持这种索引。通过使用以下事实,我们可以获得相当整洁的语法:d[1, 2, 3]Python实际上将元组传递(1, 2, 3)__getitem__

class NestedDict:
    def __init__(self, *args, **kwargs):
        self.dict = dict(*args, **kwargs)

    def __getitem__(self, keys):
        # Allows getting top-level branch when a single key was provided
        if not isinstance(keys, tuple):
            keys = (keys,)

        branch = self.dict
        for key in keys:
            branch = branch[key]

        # If we return a branch, and not a leaf value, we wrap it into a NestedDict
        return NestedDict(branch) if isinstance(branch, dict) else branch

    def __setitem__(self, keys, value):
        # Allows setting top-level item when a single key was provided
        if not isinstance(keys, tuple):
            keys = (keys,)

        branch = self.dict
        for key in keys[:-1]:
            if not key in branch:
                branch[key] = {}
            branch = branch[key]
        branch[keys[-1]] = value
Run Code Online (Sandbox Code Playgroud)

这是用法示例

# Getting an item
my_dict = NestedDict({'a': {'b': 1}})
my_dict['a', 'b'] # 1

# Setting an item
my_dict = NestedDict()
my_dict[1, 2, 3] = 4
my_dict.dict # {1: {2: {3: 4}}}

# You can even get a branch
my_dict[1] # NestedDict({2: {3: 4}})
my_dict[1][2, 3] # 4
Run Code Online (Sandbox Code Playgroud)

然后,您可以NestedDict实现通过定义也更加丰富__iter____len____contains__

而且,由于可以将任何现有的字典转换为嵌套字典,因此可以很容易地将其集成到您的代码中NestedDict(your_dict)


Art*_*ier 1

此解决方案创建另一个具有相同键的字典,然后更新现有字典:

#!/usr/bin/env python

from six.moves import reduce


def update2(input_dictionary, new_value, loc):
    """
    Update a dictionary by defining the keys.

    Parameters
    ----------
    input_dictionary : dict
    new_value : object
    loc : iterable
        Location

    Returns
    -------
    new_dict : dict

    Examples
    --------
    >>> example = {'a': {'b': 'c'}, '1': {'2': {'3': {'4': '5'}}}}

    >>> update2(example, 'new', ('a', 'b'))
    {'a': {'b': 'new'}, '1': {'2': {'3': {'4': '5'}}}}

    >>> update2(example, 'foo', ('1', '2', '3', '4'))
    {'a': {'b': 'new'}, '1': {'2': {'3': {'4': 'foo'}}}}

    >>> update2(example, 'bar', ('1', '2'))
    {'a': {'b': 'new'}, '1': {'2': 'bar'}}
    """
    new_dict = reduce(lambda x, y: {y: x}, reversed(loc), new_value)
    input_dictionary.update(new_dict)
    return input_dictionary

if __name__ == '__main__':
    import doctest
    doctest.testmod()
Run Code Online (Sandbox Code Playgroud)

使用字符串、列表或元组作为访问键