鉴于这段代码(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]()
为什么这个结果是十个 9,而不是 0,1,2,3,...9?
顺便说一句,我还打印了 s[0]~s[9],它们是 10 个函数地址,并且彼此不同。
鉴于这段代码(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]()
为什么这个结果是十个 9,而不是 0,1,2,3,...9?
顺便说一句,我还打印了 s[0]~s[9],它们是 10 个函数地址,并且彼此不同。
您已经在 上创建了一堆闭包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
@gnibbler 的代码将解决您的问题(如果有人回答,请接受他的回答)。至于为什么打印全9,看你的update
功能。您(再次,正如@gnibbler 提到的)不断返回您在中定义的 i for i in range(10)
。由于在您的原始代码中您没有update
使用函数参数调用该方法,因此它只是打印在作用域中i
定义的那个(完全不同,函数完成后将是 9)。func
i
也许为了更清楚,尝试将i
in更改func
为完全不同的名称 - 结果将是相同的。
发生的事情与此相同:
>>> 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
函数之前它们实际上仍然没有得到解决。所以,当你的每个函数被调用时,是 9。update
i
使用默认参数值,如@gnibbler 的回答,是因为i
每个update
查找的参数值都会解析为参数(它会隐藏外部变量)。这些不会改变,因为在定义函数时会评估默认参数值(这也导致了很多人迟早会遇到的可变默认错误)。