2013-06-21 47 views
6

我正在读这个关于装饰器的article嵌套函数中的python变量作用域

步骤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 如何工作的模型,我们无法调用内部函数,直到 之后,在我们调用inner的时候x应该不再存在,也许 会发生某种运行时错误。

不过,我真的不明白第二段的意思。

我明白inner()确实获得了x的值,但为什么它不打印x呢?

感谢

UPDATE

感谢所有的答案。现在我明白了原因。 的“返回内”只是一个指针到内(),但它并没有得到执行,这就是为什么内()不X作为它完全不

回答

2

称为打印您未拨打inner。您拨打了outer,返回inner,但未调用它。如果您想拨打inner,请执行foo()(因为您将outer()的结果分配到名称foo)。

您引用的段落与这个问题有点相似。你说你已经明白为什么inner得到x的价值,这正是该段落所解释的。基本上,如果在嵌套函数中使用局部变量,并且返回嵌套函数,则即使该变量定义的作用域不再处于活动状态,变量的值也会与返回的函数一起存储。通常x将在outer完成后消失,因为x只是本地的outer。但是outer返回inner,仍然需要访问x。因此x被封装到所谓的闭包中,因此稍后可以通过inner访问它。

+0

OP也在问为什么'x'仍然存在 – jamylak

+0

@jamylak:我不清楚他是否是。他说他不明白引用的段落,但也表示他明白“内部”是如何访问'x'的。 – BrenBarn

+0

以任何方式您现在已经清除了 – jamylak

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,即,即使外层函数是不是在堆栈(执行完毕)了,但仍然是从它返回的内部函数会记住它的状态(即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',) 

source code上蟒蛇如何决定它是一个封闭与否:

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

在py3.x可以人因此使用nonlocal内部函数内部的语句修改x的值。

>>> def outer(): 
     x = 1 
     def inner(): 
      nonlocal x 
      x += 1 
      print (x) 
     return inner 
...  
>>> func = outer() 
>>> func() 
2 
>>> func() 
3 
>>> func() 
4 
+2

对于非本地语句 – Tregoreg