在collections.defaultdict中使用键值

16

collections.defaultdict非常好用,特别是与lambda结合使用时:

>>> import collections
>>> a = collections.defaultdict(lambda : [None,None])
>>> a['foo']
[None, None]

有没有办法在 lambda 中使用给定的键(例如 'foo')?例如(不起作用):

>>> a = collections.defaultdict(lambda : [None]*key)
>>> a[1]
[None]
>>> a[2]
[None, None]
>>> a
defaultdict(<function <lambda> at 0x02984170>, {1: [None], 2: [None, None]})
3个回答

32

你可能想要使用__missing__,当你尝试访问字典中不存在的项时会在dict上调用它;原始的__missing__会引发异常,但是你可以在一个子类中自定义它:

class A(dict):
    def __missing__(self, key):
        value = self[key] = [None] * key
        return value

4

结合SingleNegationEliminationrplnt的答案,以及defaultdict文档,我使用了以下解决方案。

import collections
class KeyBasedDefaultDict(collections.defaultdict):
    def __missing__(self, key):
        if self.default_factory is None:
            raise KeyError(key)
        self[key] = self.default_factory(key)
        return self[key]

方法体可能只是return self.default_factory(key),但是额外的代码确保复制所有defaultdict的行为。
如问题所述的用法:
d = KeyBasedDefaultDict(lambda key: [None] * key)
d[1]
> [None]
d[2]
> [None, None]

1

这将按要求工作,尽管它可能不是最佳解决方案(您需要使用默认调用进行初始化,然后不使用它)。可能可以通过覆盖其他方法来修复它。

class NoneDict(collections.defaultdict):
    def __setitem__(self, key, value):
        super(NoneDict, self).__setitem__(key, key*[None])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接