我需要通过for循环定义python lambda函数的字典。每个lambda函数都需要相对字典键的值才能起作用,但我希望避免将此类键作为参数传递。 这是我的问题的虚拟版本。
给出
a = {'bar': 0, 'foo': 1} # a reference dictionary
dic1 = {'bar': lambda x: x['bar'], 'foo': lambda x: x['foo']}
dic2 = {key: lambda x: x[key] for key in a}
我希望dic1和dic2做同样的事情,但是只有dic1表现得与我想要的一样。 特别是
的结果print(dic1['bar'](a), dic1['foo'](a))
print(dic2['bar'](a), dic2['foo'](a))
是
0 1
1 1
代替
0 1
0 1
答案 0 :(得分:9)
它不起作用的原因与Python中的late-binding closures有关。
Python的闭包是后期绑定。这意味着在调用内部函数时会查询闭包中使用的变量的值。
根据源代码的说明,每当调用return函数时,在调用时都会在周围的范围中查找key
的值。到那时,循环已完成,并且key
保留其最终值'foo'
。
您可以通过创建一个闭包来解决此问题,该闭包可以使用默认arg像这样立即绑定到其参数:
a = {'bar': 0, 'foo': 1} # a reference dictionary
dic1 = {'bar': lambda x: x['bar'], 'foo': lambda x: x['foo']}
dic2 = {key: lambda x, key=key: x[key] for key in a}
print(dic1['bar'](a), dic1['foo'](a))
print(dic2['bar'](a), dic2['foo'](a))
结果:
0 1
0 1
答案 1 :(得分:4)
一种简单的方法是使用operator.itemgetter
:
from operator import itemgetter
a = {'bar': 0, 'foo': 1}
dic1 = {key: itemgetter(key) for key in a}
print(dic1['bar'](a), dic1['foo'](a))
# 0 1
或者,您需要将key
的每个值绑定到每个字典值,通常使用以下方法进行绑定:
a = {'bar': 0, 'foo': 1}
dic1 = {key: (lambda key: lambda x: x[key])(key) for key in a}
print(dic1['bar'](a), dic1['foo'](a))
# 0 1