Python Lambda问题

时间:2009-07-10 01:01:26

标签: python lambda

这里发生了什么?我正在尝试创建一个函数列表:

def f(a,b):
    return a*b

funcs = []

for i in range(0,10):
    funcs.append(lambda x:f(i,x))

这不符合我的期望。我希望列表的行为如下:

funcs[3](3) = 9
funcs[0](5) = 0

但是列表中的所有函数似乎都是相同的,并且将固定值设置为9:

funcs[3](3) = 27
funcs[3](1) = 9

funcs[2](6) = 54

有什么想法吗?

5 个答案:

答案 0 :(得分: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))

答案 1 :(得分:13)

是的,通常的“范围问题”(实际上是一个绑定 - 后来比你想要的问题,但它经常被这个名称调用)。你已经得到了两个最好的(因为最简单的)答案 - “假默认”i=i解决方案和functools.partial,所以我只给出经典三个中的第三个,“工厂lambda“:

for i in range(0,10):
    funcs.append((lambda i: lambda x: f(i, x))(i))

如果i=i中的函数没有被2个参数而不是1个意外调用的风险,我个人会选择funcs,但是当你需要的时候工厂函数方法值得考虑比预先绑定一个arg更富有。

答案 2 :(得分:11)

只有一个i绑定到每个lambda,与你的想法相反。这是一个常见的错误。

获得所需内容的一种方法是:

for i in range(0,10):
    funcs.append(lambda x, i=i: f(i, x))

现在,您在每个lambda闭包中创建一个默认参数i,并将循环变量i的当前绑定到它。

答案 3 :(得分:2)

所有的lambdas最终都被绑定到最后一个。请参阅此问题以获得更长的答案:

How do I create a list of Python lambdas (in a list comprehension/for loop)?

答案 4 :(得分:2)

考虑i == 9

的最终值

与任何好的python函数一样,它将在定义的范围内使用变量的值。也许lambda: varname(因为它是一种语言结构)绑定到名称而不是值,并在运行时评估该名称?

类似于:

i = 9
def foo():
    print i

i = 10
foo()

我很想知道我的答案是否正确