【问题标题】:creating a dictionary with anonymous functions in Python [duplicate]在Python中创建带有匿名函数的字典[重复]
【发布时间】:2019-11-30 22:17:56
【问题描述】:

我有一个带有一些参数的向量,我想在 Python3 中创建一个匿名 (lambda) 函数字典。

这样做的目的是创建一个可调用函数,该函数给出的值等于具有相同参数的这些函数的总和。

我什至很难用原始的 lambda 函数对象创建字典并让它们的行为一致。我使用以下代码:

import numpy as np

a = np.linspace(0,2.0,10)
func = {}
for i,val in enumerate(a):
  print(i)
  func['f{}'.format(i)] = lambda x: x**val

print(func['f0'](0.5))
print(func['f1'](0.5))
print(func['f2'](0.5))
print(func['f3'](0.5))

最终打印语句的输出给出了相同的值,而我希望它给出与 x**val 对应的值,而 val 的值来自最初构造的数组 a

我猜发生了什么事情是 lambda 函数总是引用 val 的“当前”值,在循环执行之后,它总是数组中的最后一个值?这是有道理的,因为输出是:

0
1
2
3
4
5
6
7
8
9
0.25
0.25
0.25
0.25

输出是有意义的,因为它是0.5**2.0 的结果,而指数是val 在循环中采用的最后一个值。

我不太明白这一点,因为我原以为 val 在循环运行后会超出范围,但我假设这是 lambda 函数的“魔力”的一部分,因为它们会保留他们需要更长的时间来计算范围内的函数的变量。

我想我需要做的是将 val 的“文字”值插入到 lambda 函数中,但我从来没有这样做过,也不知道怎么做。

我想知道如何正确地将val 的字面值插入到循环的每次迭代中构造的 lambda 函数中。我也想知道是否有更好的方法来完成我需要做的事情。

编辑:有人建议这个问题是重复的。我认为它是the list comprehension post 的副本,因为最佳答案几乎相同,并且使用了 lambda 函数。

我认为这不是 the lexical closures 帖子的重复,尽管我认为提及此帖子很重要。那篇文章更深入地了解了这种行为的根本原因,但最初的问题特别指出“注意避免lambda 函数”,这使它有点不同。我不确定这种谨慎回避的目的是什么,但这篇文章确实教授了有关范围界定的相关课程。

【问题讨论】:

  • 注意,了解您使用lambda 函数这一事实是完全不相关的,这一点非常重要。另一个需要理解的重要点,虽然在这里并不真正相关,但val 确实 not 在循环终止时超出范围,python 没有块范围。
  • @juanpa.arrivillaga 谢谢。您能否指出有关 Python 范围界定的参考资料?我想更好地理解它(我对范围的大部分想法/理解都是基于 C 的)。

标签: python lambda anonymous-function


【解决方案1】:

这种方法的问题在于,在您的 lambda 函数内部使用的 val 是外部的实时变量。当调用每个 lambda 时,公式中 val 使用的值是 val当前值,因此所有结果都是相同的。

解决方案是在创建每个 lambda 函数时“冻结”val 的值 - 更容易理解正在发生的事情的方法是拥有一个外部 lambda 函数,它将 val 作为输入, 并返回你的 deded (inner) lambda - 但 val 冻结在不同的范围内。请注意,外部函数被调用并立即丢弃 - 它的返回值是您拥有的原始函数:


for i,val in enumerate(a):
  print(i)
  func[f'f{i}'] = (lambda val: (lambda x: x**val))(val)

较短的版本

现在,由于 Python 将默认参数存储到函数的方式,可以将“当前val 值”作为默认参数存储在 lambda 中,并避免需要外部函数。但这破坏了 lambda 签名,并且该值的“为什么”存在更难理解 -


for i,val in enumerate(a):
  print(i)
  func[f'f{i}'] = lambda x, val=val: x**val

【讨论】:

  • 谢谢,这两种解决方案都运行良好。
猜你喜欢
  • 2016-01-30
  • 2012-05-26
  • 2011-12-03
  • 2010-12-30
  • 2014-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-07
相关资源
最近更新 更多