我是Python的新手。我的任务很简单--我需要一个函数列表,我可以用它来批量处理事情。所以我用了一些例子
fs = [lambda x: x + i for i in xrange(10)]令人惊讶的是,
[f(0) for f in fs]给了我像[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]一样的结果。这不是我所期望的,因为我希望变量i在不同的函数中有不同的值。
所以我的问题是:
i,是全局的还是本地的?i变量的引用,还是只保存了每个变量中i值的一个副本?[0, 1, .....9]呢?发布于 2011-03-04 05:48:25
它看起来有点混乱,但你可以通过这样的方式得到你想要的东西:
>>> fs = [(lambda y: lambda x: x + y)(i) for i in xrange(10)]
>>> [f(0) for f in fs]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]通常,Python支持类似于Javascript中的“闭包”概念。但是,对于列表理解中的lambda表达式的这种特殊情况,似乎i只绑定一次并接连接收每个值,让每个返回的函数都表现为i为9。上面的黑客使用捕获的y值,将i的每个值显式地传递给一个返回另一个lambda的lambda。
发布于 2011-03-04 06:55:04
您在这里遇到的问题是“早期绑定”和“后期绑定”之间的区别。
当Python从外部作用域(本例中是i)查找变量时,它使用后期绑定。这意味着它在调用函数时看到该变量的值,而不是在定义函数时看到该值。
因此,在您的示例代码中,所有10个lambda函数都看到通过循环过程( 9 )分配给9变量的最终值。
Greg的回答显示了一种强制早期绑定行为的方法(即创建一个额外的闭包并在循环中立即调用它)。
另一种常用的强制早期绑定语义的方法是“默认参数哈克”,它在函数定义时将变量绑定为默认参数:
>>> fs = [(lambda x, _i=i: x + _i) for i in xrange(10)]
>>> [f(0) for f in fs]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]这两种方法都有效。Greg的优点是不影响返回函数的签名,默认参数攻击比定义命名函数时添加额外的闭包级别要快得多,而不是使用lambda表达式。
发布于 2011-03-04 05:48:49
i是列表理解的本地变量,但是它对lambda是可用的,因为lambda在它的范围内。xrange(10)上循环一下。您可以使用lambdas (见另一个答案)来完成这个任务,但是您不会想这样做。羔羊应该非常谨慎地使用。--lambda这样做的原因是因为对于每个循环,i都是反弹的。因为我不是lambda的本地用户,所以它也会发生变化,它持有的最后一个值是9,所以您所做的就是0 + 9 10次。
https://stackoverflow.com/questions/5190146
复制相似问题