7

我正在阅读这篇关于装饰器的文章。

第 8 步,有一个函数定义为:

def outer():
    x = 1
    def inner():
       print x # 1
    return inner

如果我们通过以下方式运行它:

>>> foo = outer()
>>> foo.func_closure # doctest: +ELLIPSIS

它不打印 x。根据解释:

一切都根据 Python 的作用域规则进行 - x 是我们函数外部的局部变量。当inner 在点#1 打印x 时,Python 寻找inner 的局部变量,但没有找到它,它在封闭范围内查找,即函数outer,在那里找到它。

但是从变量生命周期的角度来看呢?我们的变量 x 是函数 external 的局部变量,这意味着它仅在函数 external 运行时存在。在外部返回之前,我们无法调用内部,因此根据我们的 Python 工作模型,在我们调用内部时 x 应该不再存在,并且可能会发生某种运行时错误。

但是,我真的不明白第二段是什么意思。

我知道 inner() 确实得到了 x 的值,但为什么它不打印 x 呢?

谢谢

更新

谢谢大家的回答。现在我明白了原因。“ return inner ”只是一个指向inner() 但它没有被执行的指针,这就是为什么 inner() 不打印 x 因为它根本没有被调用

4

2 回答 2

8

我知道 inner() 确实得到了 x 的值,但为什么它不打印 x 呢?

它不会打印出任何内容,因为您还没有调用内部函数。

>>> def outer():
        x = 1
        def inner():
               print x # 1
        return inner
...     
>>> func = outer()  
>>> func            
<function inner at 0xb61e280c>
>>> func()
1

这称为闭包,即即使外部函数不再在堆栈中(已完成执行),但从它返回的内部函数仍会记住它的状态。(即 的值x

>>> def outer():
            x = 1
            y = 2
            def inner():
                    z=3
                    print x
            return inner
...     
>>> func = outer()
>>> func.func_code.co_freevars  #returns the variables that were used in closure
('x',)

从有关 python 如何确定它是否为闭包的源代码中:

   459    if len(code.co_freevars) == 0:
   460        closure = NULL
   461    else:
   462        len(closure) == len(code.co_freevars)

在 py3.x 中,您还可以修改内部函数中xusing语句的值。nonlocal

>>> def outer():
        x = 1
        def inner():
           nonlocal x
           x += 1
           print (x)
        return inner
...     
>>> func = outer()
>>> func()
2
>>> func()
3
>>> func()
4
于 2013-06-21T05:45:07.850 回答
2

你没有打电话inner。您调用了outer,它返回inner,但没有调用它。如果你想打电话inner,做foo()(因为你把结果outer()分配给了名字foo)。

你引用的段落与这个问题有点相切。你说你已经明白为什么inner会得到 的值x,这就是那段解释的内容。基本上,如果在嵌套函数中使用了局部变量,并且返回了该嵌套函数,则该变量的值将与返回的函数一起存储,即使定义该变量的范围不再有效。通常x会在outer完成后消失,因为x只是本地的outer。但是outer返回inner,这仍然需要访问x。所以x被包裹在所谓的闭包中,所以以后仍然可以访问它inner

于 2013-06-21T05:42:39.487 回答