通过for循环定义lambdas的python字典

时间:2019-07-12 14:25:34

标签: python python-3.x

我需要通过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

2 个答案:

答案 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