词汇闭包如何工作? [英] How do lexical closures work?
问题描述
虽然我正在研究Java代码中的词法闭包问题,但我在Python中遇到了这个问题:
While I was investigating a problem I had with lexical closures in Javascript code, I came along this problem in Python:
flist = []
for i in xrange(3):
def func(x): return x * i
flist.append(func)
for f in flist:
print f(2)
请注意,此示例应避免使用lambda
.它打印"4 4 4",这是令人惊讶的.我希望"0 2 4".
Note that this example mindfully avoids lambda
. It prints "4 4 4", which is surprising. I'd expect "0 2 4".
此等效的Perl代码可以正确执行此操作:
This equivalent Perl code does it right:
my @flist = ();
foreach my $i (0 .. 2)
{
push(@flist, sub {$i * $_[0]});
}
foreach my $f (@flist)
{
print $f->(2), "\n";
}
打印"0 2 4".
您能解释一下其中的区别吗?
Can you please explain the difference ?
更新:
i
具有全局性,问题不是.这将显示相同的行为:
The problem is not with i
being global. This displays the same behavior:
flist = []
def outer():
for i in xrange(3):
def inner(x): return x * i
flist.append(inner)
outer()
#~ print i # commented because it causes an error
for f in flist:
print f(2)
如注释行所示,此时i
是未知的.仍然会打印"4 4 4".
As the commented line shows, i
is unknown at that point. Still, it prints "4 4 4".
推荐答案
Python实际上按照定义运行. 创建了三个单独的函数,但是每个函数都具有所定义的环境的封闭状态-在这种情况下,是全局环境(如果是外部函数,则为外部环境)循环放在另一个函数中).不过,这确实是问题所在-在这种环境下, i被突变了,并且所有闭包都引用了相同的i .
Python is actually behaving as defined. Three separate functions are created, but they each have the closure of the environment they're defined in - in this case, the global environment (or the outer function's environment if the loop is placed inside another function). This is exactly the problem, though - in this environment, i is mutated, and the closures all refer to the same i.
这是我能想到的最好的解决方案-创建一个函数创建器并调用那个.这将为所创建的每个函数强制不同的环境,每个函数中都具有不同的i .
Here is the best solution I can come up with - create a function creater and invoke that instead. This will force different environments for each of the functions created, with a different i in each one.
flist = []
for i in xrange(3):
def funcC(j):
def func(x): return x * j
return func
flist.append(funcC(i))
for f in flist:
print f(2)
这是将副作用和功能编程混合使用时发生的情况.
This is what happens when you mix side effects and functional programming.
这篇关于词汇闭包如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!