【问题标题】:How can I access a deeply nested dictionary using tuples?如何使用元组访问深度嵌套的字典?
【发布时间】:2013-02-11 05:54:30
【问题描述】:

我想扩展nosklo 之前的回答中给出的the autovivification example,以允许通过元组访问字典。

nosklo 的解决方案如下所示:


class AutoVivification(dict):
    """Implementation of perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            value = self[item] = type(self)()
            return value

测试:

a = AutoVivification()

a[1][2][3] = 4
a[1][3][3] = 5
a[1][2]['test'] = 6

print a

输出:

{1: {2: {'test': 6, 3: 4}, 3: {3: 5}}}

我有一个案例,我想在给定一些任意下标元组的情况下设置一个节点。如果我不知道元组有多少层,我该如何设计一种方法来设置适当的节点?

我在想也许我可以使用如下语法:

mytuple = (1,2,3)
a[mytuple] = 4

但是我在想出一个可行的实现时遇到了麻烦。


更新

我有一个基于@JCash 回答的完整示例:

class NestedDict(dict):
    """                                                                       
    Nested dictionary of arbitrary depth with autovivification.               

    Allows data access via extended slice notation.                           
    """
    def __getitem__(self, keys):
        # Let's assume *keys* is a list or tuple.                             
        if not isinstance(keys, basestring):
            try:
                node = self
                for key in keys:
                    node = dict.__getitem__(node, key)
                return node
            except TypeError:
            # *keys* is not a list or tuple.                              
                pass
        try:
            return dict.__getitem__(self, keys)
        except KeyError:
            raise KeyError(keys)
    def __setitem__(self, keys, value):
        # Let's assume *keys* is a list or tuple.                             
        if not isinstance(keys, basestring):
            try:
                node = self
                for key in keys[:-1]:
                    try:
                        node = dict.__getitem__(node, key)
                    except KeyError:
                        node[key] = type(self)()
                        node = node[key]
                return dict.__setitem__(node, keys[-1], value)
            except TypeError:
                # *keys* is not a list or tuple.                              
                pass
        dict.__setitem__(self, keys, value)

使用扩展切片表示法可以实现与上述相同的输出:

d = NestedDict()
d[1,2,3] = 4
d[1,3,3] = 5
d[1,2,'test'] = 6

【问题讨论】:

    标签: python slice autovivification


    【解决方案1】:

    这似乎有效

    def __setitem__(self, key, value):
        if isinstance(key, tuple):
            node = self
            for i in key[:-1]:
                try:
                    node = dict.__getitem__(node, i)
                except KeyError:
                    node = node[i] = type(self)()
            return dict.__setitem__(node, i, value)
        return dict.__setitem__(self, key, value)
    

    【讨论】:

    • node = node[i] = type(self)() 似乎无法正常工作。我不得不把它分成两个单独的任务。你知道为什么吗?
    • 嗯,不,我不知道我害怕。
    猜你喜欢
    • 2021-05-28
    • 2014-10-17
    • 1970-01-01
    • 2021-01-03
    • 2015-11-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 2019-06-27
    相关资源
    最近更新 更多