这里发生了什么?我正在尝试创建一个函数列表:
def f(a,b):
return a*b
funcs = []
for i in range(0,10):
funcs.append(lambda x:f(i,x))
Run Code Online (Sandbox Code Playgroud)
这不符合我的期望.我希望列表的行为如下:
funcs[3](3) = 9
funcs[0](5) = 0
Run Code Online (Sandbox Code Playgroud)
但是列表中的所有函数似乎都是相同的,并且将固定值设置为9:
funcs[3](3) = 27
funcs[3](1) = 9
funcs[2](6) = 54
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
Rya*_*yan 19
python中的lambdas是闭包....你给它的参数在评估lambda之前不会被评估.那时候i = 9,因为你的迭代完成了.
您正在寻找的行为可以通过functools.partial实现
import functools
def f(a,b):
return a*b
funcs = []
for i in range(0,10):
funcs.append(functools.partial(f,i))
Run Code Online (Sandbox Code Playgroud)
Ale*_*lli 13
是的,通常的"范围问题"(实际上是一个绑定 - 后来比你想要的问题,但它经常被这个名称调用).你已经得到了两个最好的(因为最简单的)答案 - "假默认" i=i解决方案functools.partial,所以我只给出经典三个中的第三个,即"工厂lambda":
for i in range(0,10):
funcs.append((lambda i: lambda x: f(i, x))(i))
Run Code Online (Sandbox Code Playgroud)
就个人而言,i=i如果不存在funcs使用2个参数而不是1个意外调用函数的风险,我会选择,但是当你需要比预绑定一个arg更丰富的东西时,工厂函数方法是值得考虑的.
ars*_*ars 11
只有一个i绑定到每个lambda,与你的想法相反.这是一个常见的错误.
获得你想要的东西的一种方法是:
for i in range(0,10):
funcs.append(lambda x, i=i: f(i, x))
Run Code Online (Sandbox Code Playgroud)
现在,您将i在每个lambda闭包中创建一个默认参数,并将循环变量的当前值绑定到该闭包i.
| 归档时间: |
|
| 查看次数: |
3689 次 |
| 最近记录: |