在 Python 中创建一个带有匿名函数的字典
creating a dictionary with anonymous functions in Python
我有一个带有一些参数的向量,我想在 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))
最终 print 语句的输出给出了相同的值,而我希望它给出对应于 x**val
的值,而 val
的值来自最初构造的数组 a
。
我想发生的事情是 lambda 函数总是引用 val
的 "current" 值,在执行循环后,它总是数组中的最后一个值?这是有道理的,因为输出是:
0
1
2
3
4
5
6
7
8
9
0.25
0.25
0.25
0.25
输出有意义,因为它是 0.5**2.0
的结果,指数是 val
在循环中采用的最后一个值。
我不太明白这一点,因为我认为 val
会在循环 运行 之后超出范围,但我假设这是 [=48] 的一部分=] 的 lambda 函数,因为它们会将计算函数所需的变量保留在范围内更长时间。
我想我需要做的是将 val
的 "literal" 值插入到 lambda 函数中,但我从来没有这样做过,也不知道怎么做。
我想知道如何正确地将 val
的文字值插入到在循环的每次迭代中构造的 lambda 函数中。我也想知道是否有更好的方法来完成我需要的事情。
编辑:有人认为这个问题是重复的。我认为它是 的副本,因为最佳答案几乎相同并且使用了 lambda 函数。
我认为它不是 the lexical closures post 的重复,尽管我认为提到这个 post 很重要。 post 可以更深入地了解这种行为的根本原因,但最初的问题明确指出 "mindful avoidance of lambda
functions," 这让它有点不同。我不确定这种有意回避的目的是什么,但 post 确实教授了有关范围界定的相关课程。
这种方法的问题在于,在您的 lambda 函数内部使用的 val
是外部的实时变量。当调用每个 lambda 时,公式中 val
使用的值是 val
的 current 值,因此您的所有结果都是相同的。
解决方案是在创建每个 lambda 函数时 "freeze" val
的值 - 更容易理解正在发生的事情的方法是有一个外部 lambda 函数,这将需要val
作为输入,return 您的指定(内部)lambda - 但 val
冻结在不同的范围内。请注意,外部函数被调用并立即被丢弃 - 它的 return 值是您拥有的原始函数:
for i,val in enumerate(a):
print(i)
func[f'f{i}'] = (lambda val: (lambda x: x**val))(val)
较短的版本
现在,由于 Python 存储函数默认参数的方式,可以将 "current val
value" 作为默认参数存储在 lambda 中,从而避免需要外部函数。但这破坏了 lambda 签名,并且 "why" 那个值更难理解 -
for i,val in enumerate(a):
print(i)
func[f'f{i}'] = lambda x, val=val: x**val
我有一个带有一些参数的向量,我想在 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))
最终 print 语句的输出给出了相同的值,而我希望它给出对应于 x**val
的值,而 val
的值来自最初构造的数组 a
。
我想发生的事情是 lambda 函数总是引用 val
的 "current" 值,在执行循环后,它总是数组中的最后一个值?这是有道理的,因为输出是:
0
1
2
3
4
5
6
7
8
9
0.25
0.25
0.25
0.25
输出有意义,因为它是 0.5**2.0
的结果,指数是 val
在循环中采用的最后一个值。
我不太明白这一点,因为我认为 val
会在循环 运行 之后超出范围,但我假设这是 [=48] 的一部分=] 的 lambda 函数,因为它们会将计算函数所需的变量保留在范围内更长时间。
我想我需要做的是将 val
的 "literal" 值插入到 lambda 函数中,但我从来没有这样做过,也不知道怎么做。
我想知道如何正确地将 val
的文字值插入到在循环的每次迭代中构造的 lambda 函数中。我也想知道是否有更好的方法来完成我需要的事情。
编辑:有人认为这个问题是重复的。我认为它是
我认为它不是 the lexical closures post 的重复,尽管我认为提到这个 post 很重要。 post 可以更深入地了解这种行为的根本原因,但最初的问题明确指出 "mindful avoidance of lambda
functions," 这让它有点不同。我不确定这种有意回避的目的是什么,但 post 确实教授了有关范围界定的相关课程。
这种方法的问题在于,在您的 lambda 函数内部使用的 val
是外部的实时变量。当调用每个 lambda 时,公式中 val
使用的值是 val
的 current 值,因此您的所有结果都是相同的。
解决方案是在创建每个 lambda 函数时 "freeze" val
的值 - 更容易理解正在发生的事情的方法是有一个外部 lambda 函数,这将需要val
作为输入,return 您的指定(内部)lambda - 但 val
冻结在不同的范围内。请注意,外部函数被调用并立即被丢弃 - 它的 return 值是您拥有的原始函数:
for i,val in enumerate(a):
print(i)
func[f'f{i}'] = (lambda val: (lambda x: x**val))(val)
较短的版本
现在,由于 Python 存储函数默认参数的方式,可以将 "current val
value" 作为默认参数存储在 lambda 中,从而避免需要外部函数。但这破坏了 lambda 签名,并且 "why" 那个值更难理解 -
for i,val in enumerate(a):
print(i)
func[f'f{i}'] = lambda x, val=val: x**val