我有以下python代码生成匿名函数列表:
basis = [ (lambda x: n*x) for n in [0, 1, 2] ]
print basis[0](1)
我原以为它等同于
basis = [ (lambda x: 0*x), (lambda x: 1*x), (lambda x: 2*x) ]
print basis[0](1)
然而,虽然第二个片段打印出0,这是我所期望的,但第一个打印出来2.第一段代码有什么问题,为什么它没有按预期运行?
答案 0 :(得分:8)
您可以使用默认参数在n
上创建闭包>>> basis = [ (lambda x,n=n: n*x) for n in [0, 1, 2] ]
>>> print basis[0](1)
0
答案 1 :(得分:3)
因为它"通过名称"。
也就是说,当lambda
运行时,它会执行n*x
:x
绑定到1
(它是一个参数),n
是在环境中查找(现在2 )。所以,结果是2。
答案 2 :(得分:2)
问题在于,在第一个示例中,每个lambda绑定到相同的n
- 换句话说,它捕获变量,而不是变量的值。由于n
在循环结束时的值为2,因此每个lambda对n
使用值2。
显然,您可以使用默认参数来解决此问题:
basis = [ (lambda x,n=n: n*x) for n in [0, 1, 2] ]
print basis[0](1)
由于默认参数值是常量,因此每次循环时都会评估n
右侧的n=n
,以便为您提供新的捕获值。
答案 3 :(得分:0)
我想帮助理解Karl Knechtel的评论(12月13日和10日在7:32)。下面的代码显示了如何使用生成器,原始的lambda定义给出了预期的结果,但它没有使用list或tuple:
>>> #GENERATOR
... basis = ( (lambda x: n*x) for n in [0, 1, 2] )
>>> print(type(basis))
<type 'generator'>
>>> basis = ( (lambda x: n*x) for n in [0, 1, 2] )
>>> print([x(3) for x in basis])
[0, 3, 6]
>>> #TUPLE
... basis = tuple( (lambda x: n*x) for n in [0, 1, 2] )
>>> print(type(basis))
<type 'tuple'>
>>> print([x(3) for x in basis])
[6, 6, 6]
>>> #LIST
... basis = list( (lambda x: n*x) for n in [0, 1, 2] )
>>> print(type(basis))
<type 'list'>
>>> print([x(3) for x in basis])
[6, 6, 6]
>>> #CORRECTED LIST
... basis = list( (lambda x, n=n: n*x) for n in [0, 1, 2] )
>>> print(type(basis))
<type 'list'>
>>> print([x(3) for x in basis])
[0, 3, 6]