【问题标题】:Defining a python dictionary of lambdas through a for cycle [duplicate]通过for循环定义lambda的python字典[重复]
【发布时间】:2019-07-12 14:25:34
【问题描述】:

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

【问题讨论】:

  • 这是一个有趣的问题,@jdehesa 提供了一个漂亮的解决方案,但我仍然必须问这可能有什么用?我的意思是,这是一个简单的解决方法...... a['bar']...
  • @Tomerikoo 我同意这个问题的虚拟版本可能看起来没用。在我的例子中,lambda 函数应该基于它们的键以一种非平凡的方式起作用。

标签: python python-3.x


【解决方案1】:

它不起作用的原因与Python中的late-binding closures有关。

Python 的闭包是后期绑定的。这意味着在调用内部函数时会查找闭包中使用的变量的值。

改编源码解释,每当调用返回函数时,都会在调用时在周围的作用域中查找key 的值。到那时,循环已经完成,key 的最终值为'foo'

您可以通过使用默认参数创建一个立即绑定到其参数的闭包来解决此问题,如下所示:

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

【讨论】:

  • 最好解释一下您所指向的链接所描述的内容,而不是仅仅链接它。
  • 'foo' 的最终值?感谢您的详细信息! +1
【解决方案2】:

一个简单的方法是使用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

【讨论】:

  • 感谢您的回答是正确的,但您知道为什么上述方法不起作用吗?
  • 查看我的答案以获得解释
  • @Akaisteph7 在您的代码中,所有 lambda 表达式都与理解变量 key 相关联,而不是与每次迭代时的变量值相关联,因此它们最终都使用与变量得到。我添加了一种可以避免这种情况的常用方法,即将变量作为参数依次传递给外部 lambda。
  • @jdehesa 这不是我的问题,但感谢您添加一些解释
猜你喜欢
  • 2017-09-16
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-28
  • 2013-01-04
  • 1970-01-01
  • 2013-01-15
相关资源
最近更新 更多