是否有标准类用于无限嵌套的defaultdict?

17 投票
6 回答
5629 浏览
提问于 2025-04-16 07:03

有没有人知道在Python中有没有一个标准的类,可以创建一个可以无限嵌套的字典?

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

d = defaultdict(lambda: defaultdict(lambda: defaultdict(int)))
d['abc']['def']['xyz'] += 1

如果我想再加一层(比如 d['abc']['def']['xyz']['wrt']),我就得再定义一个嵌套的defaultdict。

为了让这个模式更通用,我写了一个简单的类,重写了 __getitem__ 方法,这样可以自动创建下一个嵌套的字典。

例如:

d = InfiniteDict(('count',0),('total',0))
d['abc']['def']['xyz'].count += 0.24
d['abc']['def']['xyz'].total += 1
d['abc']['def']['xyz']['wrt'].count += 0.143
d['abc']['def']['xyz']['wrt'].total += 1

不过,有没有人知道有没有现成的实现可以用这个想法?我试着在网上搜索,但不太确定这个东西该叫什么。

6 个回答

15

这很自然地适合用递归的方式来定义。

>>> 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
29

我觉得这个一行代码几乎是完美的解决方案:

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

这是Raymond Hettinger在推特上分享的内容 (https://twitter.com/raymondh/status/343823801278140417)

14

你可以从 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

撰写回答