def makeActions():
acts=[]
for i in range(5):
print len(acts)
acts.append(lambda x: i ** x)
print acts[i]
return acts
acts=makeActions()
for i in range(5):
print acts[i](2)
Run Code Online (Sandbox Code Playgroud)
输出:
16
16
16
16
16
Run Code Online (Sandbox Code Playgroud)
预期产量:
0
1
4
9
16
Run Code Online (Sandbox Code Playgroud)
Aar*_*lla 23
因为i在lambda中可能不是你所期望的.要验证这一点,请更改代码:
acts.append(lambda x: (i, i ** x))
Run Code Online (Sandbox Code Playgroud)
现在print告诉你价值i:
(4, 16)
(4, 16)
(4, 16)
(4, 16)
(4, 16)
Run Code Online (Sandbox Code Playgroud)
这意味着lambda它不会复制值i但保留对变量的引用,因此所有lambdas都看到相同的值.要解决此问题,请复制i:
acts.append(lambda x, i=i: (i, i ** x))
Run Code Online (Sandbox Code Playgroud)
小小的内部i=i创建了一个本地副本.ilambda
[编辑]现在为什么这样?在2.1之前的Python版本中,本地函数(即在其他函数内定义的函数)无法在同一范围内看到变量.
def makeActions():
acts=[]
for i in range(5):
print len(acts)
def f(x): # <-- Define local function
return i ** x
acts.append(f)
print acts[i]
return acts
Run Code Online (Sandbox Code Playgroud)
然后你会得到一个i未定义的错误.lambda可以看到封闭的范围,代价是一种有点奇怪的语法.
这种行为已在最新版本的Python(2.5,IIRC)中得到修复.使用这些旧版本的Python,您必须编写:
def f(x, i=i): # <-- Must copy i
return i ** x
Run Code Online (Sandbox Code Playgroud)
由于修复(参见PEP 3104),f()可以看到相同范围内的变量,因此lambda不再需要.
因为你创建的所有lambda函数都绑定到i,它在循环结束时变为4,并且我们都知道4*4 = 16
避免使用嵌套函数(闭包)创建函数,例如
def makePowerFunc(base):
def powerFunc(x):
return base**x
return powerFunc
def makeActions():
acts=[]
for i in range(5):
acts.append(makePowerFunc(i))
return acts
acts=makeActions()
for i in range(5):
print acts[i](2)
Run Code Online (Sandbox Code Playgroud)
输出:
0
1
4
9
16
Run Code Online (Sandbox Code Playgroud)
还有其他方法可以解决它,但最好有一个命名的嵌套函数而不是lambda,你可以用这样的闭包做更多的事情
这是违反直觉或至少不太常见的语法.我想你的意思是:
acts.append(lambda x, i = i: i ** x)
Run Code Online (Sandbox Code Playgroud)
这将输出:
0
1
4
9
16
Run Code Online (Sandbox Code Playgroud)
FN.在你的版本中,
acts.append(lambda x, i: i ** x)
Run Code Online (Sandbox Code Playgroud)
拉姆达函数创建,但他们都提到了本地i自循环,它停在i = 4,所以所有的lambda表达式都在说:lambda x: 4 ** x,因此
for i in range(5):
print acts[i](2)
Run Code Online (Sandbox Code Playgroud)
将打印所有16s.
FFN.关于破碎的lambda的博客文章:http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/
| 归档时间: |
|
| 查看次数: |
303 次 |
| 最近记录: |