首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于以下代码的运行结果(Python,少于10行)

关于以下代码的运行结果(Python,少于10行)
EN

Stack Overflow用户
提问于 2012-08-15 13:34:35
回答 3查看 93关注 0票数 0

给定这段代码(Python)

代码语言:javascript
复制
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个函数地址,它们彼此之间是不同的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-08-15 13:38:24

您已经在i上创建了一组闭包,但是它们都共享相同的(最终) i

你需要像这样做一个小小的修改

代码语言:javascript
复制
>>> 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
票数 3
EN

Stack Overflow用户

发布于 2012-08-15 13:50:30

@gnibbler的代码会修复你的代码(所以如果有人的话请接受他的回答)。至于为什么它打印所有的9,看看你的update函数。您(同样,就像@gnibbler提到的那样)不断返回您在for i in range(10)中定义的i。因为在您的原始代码中没有使用函数参数调用update方法,所以它只是打印在func作用域中定义的i (一个完全不同的i,在函数完成后将是9)。

为了更清楚,可以尝试将func中的i更改为一个完全不同的名称-结果将是相同的。

票数 0
EN

Stack Overflow用户

发布于 2012-08-15 13:59:59

正在发生的事情是这样的:

代码语言:javascript
复制
>>> a = 5
>>> def foo(): print(a)

>>> foo()
5
>>> a = 10
>>> foo()
10
>>> a = 'fred'
>>> foo()
fred

也是这样的:

代码语言:javascript
复制
>>> 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 )。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11964567

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档