Python defaultdict 和 lambda
在别人的代码中,我看到以下两行:
x = defaultdict(lambda: 0)
y = defaultdict(lambda: defaultdict(lambda: 0))
因为defaultdict的参数是一个默认工厂,我觉得第一行的意思是,当我用一个不存在的键k去调用x[k]时(比如像v=x[k]这样的语句),键值对(k,0)会自动添加到字典中,就好像先执行了语句x[k]=0一样。我理解得对吗?
那y又是什么呢?看起来默认工厂会创建一个默认值为0的defaultdict。但这具体意味着什么呢?我在Python的命令行里试着玩了一下,但没搞明白它到底是什么。
5 个回答
defaultdict
是一个特殊的字典,它在创建的时候需要一个不带参数的函数,这个函数会在找不到某个键的时候被调用,正如你所说的那样。
lambda: 0
这个函数每次调用都会返回零,但更推荐的做法是使用 defaultdict(int)
,这样也能达到同样的效果。
至于第二部分,作者希望在顶层字典中找不到某个键时,能够创建一个新的 defaultdict(int)
,或者说是一个嵌套字典。
你说得对,第一个部分的功能是这样的。至于 y
,它会创建一个默认值为0的字典,当你查找一个不存在的键时,就会返回0。所以你可以把它想象成一个嵌套的字典。下面是一个例子:
y = defaultdict(lambda: defaultdict(lambda: 0))
print y['k1']['k2'] # 0
print dict(y['k1']) # {'k2': 0}
如果你想创建一个和这个嵌套字典结构相同的字典,但不使用默认字典,你就需要先为 y['k1']
创建一个内部字典,然后再把 y['k1']['k2']
设置为0。但是使用默认字典时,当它遇到一个它没见过的键时,这些操作都是自动完成的:
y = {}
y['k1'] = {}
y['k1']['k2'] = 0
下面这个函数可以帮助你在解释器中玩一下,以便更好地理解这个概念:
def to_dict(d):
if isinstance(d, defaultdict):
return dict((k, to_dict(v)) for k, v in d.items())
return d
这个函数会返回一个与嵌套的默认字典等价的普通字典,这样看起来会更容易理解,比如:
>>> y = defaultdict(lambda: defaultdict(lambda: 0))
>>> y['a']['b'] = 5
>>> y
defaultdict(<function <lambda> at 0xb7ea93e4>, {'a': defaultdict(<function <lambda> at 0xb7ea9374>, {'b': 5})})
>>> to_dict(y)
{'a': {'b': 5}}
我觉得第一行的意思是,当我用一个不存在的键
k
来调用x[k]
时(比如像v=x[k]
这样的语句),字典里会自动添加一个键值对(k,0)
,就好像先执行了x[k]=0
一样。
没错。更常见的写法是
x = defaultdict(int)
对于 y
来说,当你执行 y["ham"]["spam"]
时,如果键 "ham"
不存在,它会被插入到 y
中。与之关联的值会变成一个 defaultdict
,在这个字典里,"spam"
会自动插入,并且值为 0
。
也就是说,y
是一种“二级”的 defaultdict
。如果 "ham" 不在 y
中,那么评估 y["ham"]["spam"]
就像执行
y["ham"] = {}
y["ham"]["spam"] = 0
在普通的 dict
中一样。