python – 词法闭包如何工作?
作者:互联网
当我在调查Javascript代码中的词法闭包问题时,我在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”.
这个等效的Perl代码是正确的:
my @flist = ();
foreach my $i (0 .. 2)
{
push(@flist, sub {$i * $_[0]});
}
foreach my $f (@flist)
{
print $f->(2), "\n";
}
打印“0 2 4”.
你能解释一下这个区别吗?
更新:
问题不在于我是全球性的.这显示相同的行为:
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)
正如评论专线所示,那时我还不得而知.不过,它打印“4 4 4”.
解决方法:
Python实际上是按照定义的行为.创建了三个单独的函数,但它们各自具有它们所定义的环境的闭包 – 在这种情况下,是全局环境(如果循环放在另一个函数内,则为外部函数的环境).这正是问题所在 – 在这种环境中,我是变异的,闭包都是指同一个i.
这是我能想出的最佳解决方案 – 创建一个函数创建器并调用它.这将为每个创建的函数强制使用不同的环境,每个函数都有不同的i.
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)
当您混合副作用和函数式编程时会发生这种情况.
标签:late-binding,python,closures,lazy-evaluation 来源: https://codeday.me/bug/20190911/1803162.html