0

鉴于这段代码(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 个函数地址,并且彼此不同。

4

3 回答 3

3

您已经在 上创建了一堆闭包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-15T05:38:23.637 回答
0

@gnibbler 的代码将解决您的问题(如果有人回答,请接受他的回答)。至于为什么打印全9,看你的update功能。您(再次,正如@gnibbler 提到的)不断返回您在中定义的 i for i in range(10)。由于在您的原始代码中您没有update使用函数参数调用该方法,因此它只是打印在作用域中i定义的那个(完全不同,函数完成后将是 9)。funci

也许为了更清楚,尝试将iin更改func为完全不同的名称 - 结果将是相同的。

于 2012-08-15T05:50:30.407 回答
0

发生的事情与此相同:

>>> 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。updatei

使用默认参数值,如@gnibbler 的回答,是因为i每个update查找的参数值都会解析为参数(它会隐藏外部变量)。这些不会改变,因为在定义函数时会评估默认参数值(这也导致了很多人迟早会遇到的可变默认错误)。

于 2012-08-15T05:59:59.377 回答