当我在调查Javascript代码中的词法闭包问题时,我在Python中遇到了这个问题:
flist = []
for i in xrange(3):
def func(x): return x * i
flist.append(func)
for f in flist:
print f(2)
Run Code Online (Sandbox Code Playgroud)
请注意,此示例谨慎避免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";
}
Run Code Online (Sandbox Code Playgroud)
打印"0 2 4".
你能解释一下这个区别吗?
更新:
这个问题是不是与i是全球性的.这显示相同的行为:
flist = []
def outer():
for i in xrange(3):
def inner(x): return x * i …Run Code Online (Sandbox Code Playgroud) 这一点Python不起作用:
def make_incrementer(start):
def closure():
# I know I could write 'x = start' and use x - that's not my point though (:
while True:
yield start
start += 1
return closure
x = make_incrementer(100)
iter = x()
print iter.next() # Exception: UnboundLocalError: local variable 'start' referenced before assignment
Run Code Online (Sandbox Code Playgroud)
我知道如何解决这个错误,但请耐心等待:
这段代码工作正常:
def test(start):
def closure():
return start
return closure
x = test(999)
print x() # prints 999
Run Code Online (Sandbox Code Playgroud)
为什么我可以读取start闭包内的变量而不是写入它?导致这种start变量处理的语言规则是什么?
更新:我发现这个SO帖子相关(答案不仅仅是问题):读/写Python闭包