使用自然下标创建三维OrderedDict

2rs*_*2ts 4 python ordereddictionary python-2.7 defaultdict

我想要一个具有以下属性的字典结构:

  1. 双嵌套(所以,这么多单词都是三维的)
  2. 记住每个级别添加到其中的内容的顺序

所以,如果我像这样添加项目:

# d = something dict-ish
d['a']['b']['c'] = 'd'
d['a'][1][2] = 3
d['f']['g']['e'] = 'g'
d['f'][5][6] = 7
d['a']['foo']['bar'] = 'hello world'
Run Code Online (Sandbox Code Playgroud)

以下理解的结果:

[(i, j, k, d[i][j][k]) for i in d for j in d[i] for k in d[i][j]]
Run Code Online (Sandbox Code Playgroud)

将会:

[('a', 'b', 'c', 'd'), ('a', 1, 2, 3), ('a', 'foo', 'bar', 'hello world'), ('f', 'g', 'e', 'g'), ('f', 5, 6, 7)]
Run Code Online (Sandbox Code Playgroud)

我已经尝试使用a defaultdict为新键强制执行此结构,因此我不必长途键入它,如下所示:

# long way
d = OrderedDict()
d['a'] = OrderedDict([('b', OrderedDict([('c', 'd')]))])
d['a'][1] = OrderedDict([(2,3)])

# tried to use defaultdict
d = defaultdict(lambda: defaultdict(lambda: OrderedDict()))
d['a']['b']['c'] = 'd'
d['a'][1][2] = 3
Run Code Online (Sandbox Code Playgroud)

但是defaultdict不记得前两个级别的顺序.我不确定如何合并行为,所以显然前两个级别正在产生defaultdict行为,因为我已经宣布d这样做.我怎样才能实现我想要的结构?

Mar*_*ers 6

您只需要子类化OrderedDict并添加一个__missing__函数:

from collections import OrderedDict

class DefaultOrderedDict(OrderedDict):
    def __missing__(self, key):
        self[key] = type(self)()
        return self[key]
Run Code Online (Sandbox Code Playgroud)

默认 dict类型将调用__missing__,如果本发明的方法养之前KeyError,这是什么defaultdict类型的利用了.

请参阅dict文档(向下滚动到d[key]说明):

版本2.5中的新增内容:如果dict的子类定义了方法__missing__(),则如果不存在键,则d[key]操作将使用键作为参数调用该方法.该d[key]操作然后返回或引发任何退回或募集的__missing__(key)通话如果该键不存在.没有其他操作或方法调用__missing__().如果__missing__()未定义,KeyError则引发.__missing__()必须是一种方法; 它不能是实例变量.

演示:

>>> d = DefaultOrderedDict()
>>> d['a']['b']['c'] = 'd'
>>> d['a'][1][2] = 3
>>> d['f']['g']['e'] = 'g'
>>> d['f'][5][6] = 7
>>> d['a']['foo']['bar'] = 'hello world'
>>> [(i, j, k, d[i][j][k]) for i in d for j in d[i] for k in d[i][j]]
[('a', 'b', 'c', 'd'), ('a', 1, 2, 3), ('a', 'foo', 'bar', 'hello world'), ('f', 'g', 'e', 'g'), ('f', 5, 6, 7)]
Run Code Online (Sandbox Code Playgroud)