为什么这个创建curried函数列表的尝试不起作用?
def p(x, num):
print x, num
def test():
a = []
for i in range(10):
a.append(lambda x: p (i, x))
return a
>>> myList = test()
>>> test[0]('test')
9 test
>>> test[5]('test')
9 test
>>> test[9]('test')
9 test这里发生了什么事?
我期望上面的函数能做的事情是:
import functools
def test2():
a = []
for i in range (10):
a.append(functools.partial(p, i))
return a
>>> a[0]('test')
0 test
>>> a[5]('test')
5 test
>>> a[9]('test')
9 test发布于 2009-05-08 20:12:59
在Python中,在循环和分支中创建的变量没有作用域。使用lambda创建的所有函数都有一个对相同i变量的引用,该变量在循环的最后一次迭代中被设置为9。
解决方案是创建一个返回函数的函数,从而限定迭代器变量的作用域。这就是functools.partial()方法有效的原因。例如:
def test():
def makefunc(i):
return lambda x: p(i, x)
a = []
for i in range(10):
a.append(makefunc(i))
return a发布于 2009-05-09 06:58:27
你也可以将I绑定到懒惰的外部lambda上。
def p(x, num):
print x, num
def test():
a = []
for i in range(10):
a.append((lambda i :lambda x: p (i, x))(i))
return a发布于 2013-04-06 00:34:31
我一直很困惑,为什么这个不能工作。谢谢你的解释,'a paid nerd‘。我个人更喜欢这个解决方案:
for i in range(10):
a.append(lambda num, val_i=i: p (val_i, num))请注意lambda的val_i=i默认参数,它允许在循环期间捕获i的瞬时值,同时仍然有效地使lambda成为1个变量的函数。(顺便说一句:将您的x更改为num以匹配p的定义。)我更喜欢它,因为:
导入函数非常接近最初的想法,避免了定义新的命名函数,这正是lambda...
functools
我只是搜索了一下,找到了同样问题的更详细的解释:Scope of python lambda functions and their parameters
https://stackoverflow.com/questions/841555
复制相似问题