我正在尝试创建一个具有可变深度和list和int类型的多级dict。
数据结构如下所示
A
--B1
-----C1=1
-----C2=[1]
--B2=[3]
D
--E
----F
------G=4
如果是上述数据结构,则最后一个值可以是int
或list
。
如果上述数据结构具有 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'
那么有没有办法只使用附加方法列表?
答案 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__
与其工厂函数一样)。