我正在阅读关于装饰者的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,因为它根本没有被调用
答案 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
访问它。