具有可变深度且具有list和int类型的多级defaultdict

时间:2017-08-16 06:51:48

标签: python dictionary defaultdict

我正在尝试创建一个具有可变深度和list和int类型的多级dict。

数据结构如下所示

A
--B1
-----C1=1
-----C2=[1]
--B2=[3]
D
--E
----F
------G=4

如果是上述数据结构,则最后一个值可以是intlist

如果上述数据结构具有 only int ,则可以使用以下代码轻松实现:

from collections import defaultdict
f = lambda: defaultdict(f)
d = f()
d['A']['B1']['C1'] = 1

但是,由于最后一个值 列表 int ,因此对我来说有点问题。

现在我们可以使用两种方式在列表中插入数据。

d['A']['B1']['C2']= [1]
d['A']['B1']['C2'].append([2])

但是当我只使用append方法时,它会导致错误。

错误是:

AttributeError: 'collections.defaultdict' object has no attribute 'append'

那么有没有办法只使用附加方法列表

1 个答案:

答案 0 :(得分:0)

如果defaultdict密钥尚未存在,您无法使用当前基于d['A']['B1']['C2'].append(1)的结构使'C2'正常工作,因为数据结构不能告诉未知密钥应该对应于列表而不是另一层字典。它不知道你要回复的价值会调用什么方法,所以它不知道它不应该返回一个字典(就像它第一次查找时所做的那样{ {1}}和'A')。

对于裸整数而言,这不是一个问题,因为对于那些您直接分配给新密钥的人(并且所有较早的级别都是字典)。当您进行分配时,数据结构不会创建该值,您可以使用任何类型。

现在,如果您的密钥在某种程度上是独特的,那么给定像'B'这样的密钥您可以确定它应该对应于列表,您可能有机会。您可以编写自己的'C2'子类,定义dict方法来处理以您自己的特殊方式不存在的键的查找:

__missing__

这是一个使用魔术键函数运行的示例,该函数使任何偶数长度键默认为列表,而奇数长度键默认为dict:

def Tree(dict):
    def __missing__(self, key):
        if key_corresponds_to_list(key): # magic from somewhere
            result = self[key] = []
        else:
            result = self[key] = Tree()
        return result

    # you might also want a custom __repr__

你可能实际上并不想使用全局函数来控制这样的类,我只是以此为例。如果你采用这种方法,我建议将逻辑直接放入> def key_corresponds_to_list(key): return len(key) % 2 == 0 > t = Tree() > t["A"]["B"]["C2"].append(1) # the default value for C2 is a list because it's even length > t {'A': {'B': {'C2': [1]}}} > t["A"]["B"]["C10"]["D"] = 2 # C10's another layer of dict, since it's length is odd > t {'A': {'B': {'C10': {'D': 2}, 'C2': [1]}}} # it didn't matter what length D was though 方法(或者可以将函数作为参数传递,如__missing__与其工厂函数一样)。