Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 是否存在用于无限嵌套defaultdict的标准类?_Python_Dictionary_Nested_Infinite_Defaultdict - Fatal编程技术网

Python 是否存在用于无限嵌套defaultdict的标准类?

Python 是否存在用于无限嵌套defaultdict的标准类?,python,dictionary,nested,infinite,defaultdict,Python,Dictionary,Nested,Infinite,Defaultdict,有人知道Python中是否有一个无限嵌套字典的标准类吗 我发现自己在重复这个模式: d = defaultdict(lambda: defaultdict(lambda: defaultdict(int))) d['abc']['def']['xyz'] += 1 如果我想添加“另一层”(例如,d['abc']['def']['xyz']['wrt']),我必须定义另一个defaultdicts嵌套 为了推广这种模式,我编写了一个简单的类,它覆盖\uuuu getitem\uuuu以自动创建下

有人知道Python中是否有一个无限嵌套字典的标准类吗

我发现自己在重复这个模式:

d = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
d['abc']['def']['xyz'] += 1
如果我想添加“另一层”(例如,
d['abc']['def']['xyz']['wrt']
),我必须定义另一个defaultdicts嵌套

为了推广这种模式,我编写了一个简单的类,它覆盖
\uuuu getitem\uuuu
以自动创建下一个嵌套字典

e、 g


然而,有人知道这个想法已经存在了吗?我尝试过谷歌搜索,但我不确定这将被称为什么。

这自然适合递归定义

>>> import collections
>>> def nested_dd():
...     return collections.defaultdict(nested_dd)
...
>>> foo = nested_dd()
>>> foo
defaultdict(<function nested_dd at 0x023F0E30>, {})
>>> foo[1][2]=3
>>> foo[1]
defaultdict(<function nested_dd at 0x023F0E30>, {2: 3})
>>> foo[1][2]
3
导入集合 >>>def嵌套的_dd(): ... 返回集合.defaultdict(嵌套的\u dd) ... >>>foo=nested_dd() >>>福 defaultdict(,{}) >>>foo[1][2]=3 >>>傅[1] defaultdict(,{2:3}) >>>foo[1][2] 3. 这很接近:

class recursivedefaultdict(defaultdict):
    def __init__(self, attrFactory=int):
        self.default_factory = lambda : type(self)(attrFactory)
        self._attrFactory = attrFactory
    def __getattr__(self, attr):
        newval = self._attrFactory()
        setattr(self, attr, newval)
        return newval

d = recursivedefaultdict(float)
d['abc']['def']['xyz'].count += 0.24  
d['abc']['def']['xyz'].total += 1  

data = [
    ('A','B','Z',1),
    ('A','C','Y',2),
    ('A','C','X',3),
    ('B','A','W',4),
    ('B','B','V',5),
    ('B','B','U',6),
    ('B','D','T',7),
    ]

table = recursivedefaultdict(int)
for k1,k2,k3,v in data:
    table[k1][k2][k3] = v
这不是您想要的,因为嵌套最深的级别没有“count”或“total”的默认0值

编辑: 啊,现在可以了-只需要添加一个
\uuu getattr\uuuu
方法,就可以了

编辑2:
现在,您可以为属性定义除INT之外的其他factory方法。但它们必须是相同的类型,不能让count为float,total为int。

您可以从
defaultdict
派生出您想要的行为:

class InfiniteDict(defaultdict):
   def __init__(self):
      defaultdict.__init__(self, self.__class__)

class Counters(InfiniteDict):
   def __init__(self):
      InfiniteDict.__init__(self)                                               
      self.count = 0
      self.total = 0

   def show(self):
      print "%i out of %i" % (self.count, self.total)
此类的用法如下所示:

>>> d = Counters()
>>> d[1][2][3].total = 5
>>> d[1][2][3].show()
0 out of 5
>>> d[5].show()
0 out of 0

由某事物的答案启发的理想解决方案:

from collections import defaultdict

class InfiniteDict(defaultdict):
   def __init__(self, **kargs):
      defaultdict.__init__(self, lambda: self.__class__(**kargs))
      self.__dict__.update(kargs)

d = InfiniteDict(count=0, total=0)
d['abc']['def'].count += 0.25
d['abc']['def'].total += 1
print d['abc']['def'].count
print d['abc']['def'].total
d['abc']['def']['xyz'].count += 0.789
d['abc']['def']['xyz'].total += 1
print d['abc']['def']['xyz'].count
print d['abc']['def']['xyz'].total

我认为这一行是一个近乎完美的解决方案:

>>> from collections import defaultdict
>>> infinite_defaultdict = lambda: defaultdict(infinite_defaultdict)
>>> d = infinite_defaultdict() 
>>> d['x']['y']['z'] = 10

Raymond Hettinger在Twitter上的文章()

如果八年后你仍然在考虑如何用一句话来表达:

from collections import defaultdict

t = defaultdict(lambda: defaultdict(t.default_factory))

非常整洁,但与我发布的答案有相同的缺陷,不支持叶节点上的“count”和“total”零值。@Paul--的确;你不能既有蛋糕又吃!对
count
total
的特殊支持破坏了对称性,因此必须将其硬连接到类的某个地方。@aaronasterling:任何递归限制都没有问题,因为函数不会递归调用自身。对了,我错过了这一部分并一直在寻找:)对不起,katriealex。对不起,但我不认为这是可行的,因为如果你看到OP的问题,他正在用默认的默认值进行大量的计算,而不仅仅是赋值!!!谢谢这与我所寻找的最接近,并帮助我找到了确切的解决方案。次要建议:您可以使用
functools.partial(键入(self),attrFactory)
。此解决方案的排名应该更高!
from collections import defaultdict

t = defaultdict(lambda: defaultdict(t.default_factory))