在collections.defaultdict中使用键
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 个回答
1
这样做可以达到你想要的效果,虽然这可能不是最好的解决办法(你需要先用默认的方式初始化它,然后就不要再用了)。可能通过重写其他一些方法可以解决这个问题。
class NoneDict(collections.defaultdict):
def __setitem__(self, key, value):
super(NoneDict, self).__setitem__(key, key*[None])
4
结合了来自 SingleNegationElimination 和 rplnt 的回答,以及 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]
32
你可能想要使用 __missing__
这个功能。当你试图访问一个字典中不存在的项目时,它会被调用。默认情况下,__missing__
会抛出一个错误,但在你自己创建的子类中,你可以根据需要做任何事情:
class A(dict):
def __missing__(self, key):
value = self[key] = [None] * key
return value