给定这段代码(Python)
s = [None]*10
def func():
for i in range(10):
def update():
print i,
s[i] = update
func()
for i in range(10):
s[i]()为什么这个结果是10个9,而不是0,1,2,3,...9?
顺便说一句,我还打印了s~s9,它们是10个函数地址,它们彼此之间是不同的。
发布于 2012-08-15 13:38:24
您已经在i上创建了一组闭包,但是它们都共享相同的(最终) i值
你需要像这样做一个小小的修改
>>> s = [None]*10
>>> def func():
... for i in range(10):
... def update(i=i):
... print i,
... s[i] = update
...
>>> func()
>>> for i in range(10):
... s[i]()
...
0 1 2 3 4 5 6 7 8 9发布于 2012-08-15 13:50:30
@gnibbler的代码会修复你的代码(所以如果有人的话请接受他的回答)。至于为什么它打印所有的9,看看你的update函数。您(同样,就像@gnibbler提到的那样)不断返回您在for i in range(10)中定义的i。因为在您的原始代码中没有使用函数参数调用update方法,所以它只是打印在func作用域中定义的i (一个完全不同的i,在函数完成后将是9)。
为了更清楚,可以尝试将func中的i更改为一个完全不同的名称-结果将是相同的。
发布于 2012-08-15 13:59:59
正在发生的事情是这样的:
>>> a = 5
>>> def foo(): print(a)
>>> foo()
5
>>> a = 10
>>> foo()
10
>>> a = 'fred'
>>> foo()
fred也是这样的:
>>> def bar(): return b
>>> bar()
Traceback (most recent call last):
File "<pyshell#30>", line 1, in <module>
bar()
File "<pyshell#29>", line 1, in bar
def bar(): return b
NameError: global name 'b' is not defined
>>> b = 3
>>> bar()
3您在函数中使用的变量直到函数被调用时才会被解析,而不是在函数被写入时解析。有一种称为闭包的魔力,这意味着在其他函数中定义的函数(因为您的update函数是在func中定义的)仍然可以访问外部函数中定义的所有变量-但在调用函数之前,它们实际上仍然不会得到解析。因此,在调用每个update函数时,i为9。
使用默认参数值,就像在@gnibbler的答案中一样,因为每个update查找的i将解析为参数(隐藏外部变量)。这些都不会改变,因为默认参数值是在定义函数时计算的(这也会导致许多人迟早会遇到的mutable defaults bug )。
https://stackoverflow.com/questions/11964567
复制相似问题