编程语言
首页 > 编程语言> > python – 词法闭包如何工作?

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