嵌套函数中的python变量范围

时间:2013-06-21 05:41:00

标签: python function scope

我正在阅读关于装饰者的article

步骤8 ,有一个定义为:

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

如果我们按以下方式运行:

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

它不会打印x。根据解释:

  

一切都符合Python的范围规则 - x是本地的   我们的函数外部的变量。当内部打印x点#1 Python   寻找一个局部变量到内部,而不是找到它看起来   封闭作为外部功能的范围,在那里找到它。

     

但是从变量生命周期的角度来看呢?我们的   变量x是函数外部的局部变量,这意味着它只存在   而外部函数正在运行。我们无法打电话给内心   之后返回外部所以根据我们的模型如何Python   在我们称之为内心的时候,x应该不再存在了   应该发生某种运行时错误。

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

我理解inner()确实得到x的值,但是为什么它不打印x out?

感谢

更新

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

2 个答案:

答案 0 :(得分:7)

  

我理解inner()确实得到了x的值,但为什么它不打印   x out?

它没有打印出任何东西,因为你还没有调用内部函数。

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

这称为closure,即使外部函数不在堆栈中(已完成执行),但仍然从其返回的内部函数会记住它的状态。(即{{1}的值})

x

source code关于python如何判断它是否为闭包:

>>> 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',)

在py3.x中,您还可以使用内部函数内的 459 if len(code.co_freevars) == 0: 460 closure = NULL 461 else: 462 len(closure) == len(code.co_freevars) 语句修改x的值。

nonlocal

答案 1 :(得分:2)

您没有致电inner。您已调用outer,它会返回inner,但不会调用它。如果您想致电inner,请执行foo()(因为您将outer()的结果与foo名称联系起来。)

您引用的段落与此问题相关。您说您已经理解为什么inner获得x的值,这是该段解释的内容。基本上,如果在嵌套函数中使用局部变量,并且返回嵌套函数,则变量的值与返回的函数一起存储,即使该变量的定义范围不再处于活动状态。通常情况x会在outer完成后消失,因为x只是outer的本地。但outer会返回inner,但仍需要访问x。所以x被包含在所谓的闭包中,所以稍后仍然可以通过inner访问它。