>>> inn.func_closure
(<cell at 0x10c9807c0: str object at 0x10c9b0990>,
<cell at 0x10c980f68: str object at 0x10c9eaf30>,
<cell at 0x10c989130: str object at 0x10c831b98>)
>>> for i in inn.func_closure:
... print i.cell_contents
...
free
am
I
>>>
这里当我们调用 inn 时,它会引用所有保存自由变量,所以我们得到 I am free variable
def initCounter():
x = 0;
def counter ():
x += 1 ##Error, x not defined
print x
return counter
count = initCounter();
count(); ##Error
count();
count();
7 回答
Python 2没有闭包 - 它有类似闭包的解决方法 .
已经给出的答案中有很多例子 - 将变量复制到内部函数,修改内部函数上的对象等 .
在Python 3中,支持更明确 - 而且简洁:
用法:
nonlocal
关键字将内部函数绑定到显式提到的外部变量,实际上将其封闭 . 因此更明确地'closure' .得到:
这是一个闭包是什么以及它如何使用的例子 .
当函数可以从已完成执行的封闭范围访问局部变量时,就会发生闭包 .
当调用
make_printer
时,将新的帧放在堆栈上,其中printer
函数的编译代码为常量,msg
的值为本地 . 然后它创建并返回该函数 . 因为函数printer
引用msg
变量,所以在返回make_printer
函数后它保持活动状态 .所以,如果你的嵌套函数没有
当
然后他们不是关闭 .
这是一个嵌套函数的例子,它不是一个闭包 .
在这里,我们将值绑定到参数的默认值 . 在创建函数
printer
时会发生这种情况,因此在make_printer
返回后不需要保留对printer
外部的msg
值的引用 .msg
只是此上下文中函数printer
的正常局部变量 .The question has already been answered by aaronasterling
但是,有人可能会对变量如何存储在引擎盖下感兴趣 .
Before coming to the snippet:
闭包是从其封闭环境继承变量的函数 . 当你将函数回调作为参数传递给另一个将执行I / O的函数时,这个回调函数将在稍后调用,并且这个函数将 - 几乎神奇地 - 记住声明它的上下文,以及所有可用的变量在这种情况下 .
如果函数不使用自由变量,则它不会形成闭包 .
如果有另一个内部级别使用自由变量 - 所有以前的级别都保存词法环境(最后的例子)
函数属性
func_closure
in python < 3.X or closure in python > 3.X save the free variables.python中的每个函数都有这个闭包属性,但如果没有自由变量,它不会保存任何内容 .
example: of closure attributes but no content inside as there is no free variable.
NB: FREE VARIABLE IS MUST TO CREATE A CLOSURE.
我将解释使用与上面相同的代码段:
并且所有Python函数都有一个闭包属性,所以让我们检查与闭包函数关联的封闭变量 .
这是函数
func_closure
的属性func_closure
closure
属性返回一个单元格对象元组,其中包含封闭范围中定义的变量的详细信息 .func_closure中的第一个元素可以是None或包含函数自由变量绑定的单元格元组,它是只读的 .
在上面的输出中你可以看到
cell_contents
,让我们看看它存储的内容:因此,当我们调用函数
printer()
时,它会访问cell_contents
中存储的值 . 这就是我们如何得到输出'Foo!'我将再次解释使用上面的代码片段进行一些更改:
在上面的代码片段中,我不打印打印机功能内的msg,因此它不会创建任何自由变量 . 由于没有自由变量,闭包内部将没有内容 . 这正是我们上面看到的 .
现在我将解释另一个不同的片段,以清除所有
Free Variable
与Closure
:因此,我们看到
func_closure
属性是闭包单元格的元组,我们可以明确地引用它们及其内容 - 单元格具有属性"cell_contents"这里当我们调用
inn
时,它会引用所有保存自由变量,所以我们得到I am free variable
Python对闭包的支持很弱 . 要查看我的意思,请使用带有JavaScript的闭包来使用以下计数器示例:
Closure非常优雅,因为它为这样的函数提供了具有“内部存储器”的能力 . 从Python 2.7开始,这是不可能的 . 如果你试试
您将收到一条错误消息,指出x未定义 . 但是,如果其他人表现出来,怎么可能呢?你可以打印吗?这是因为Python如何管理函数变量范围 . 虽然内部函数可以__69935_外部函数的变量,但它们不能 write .
这真是一种耻辱 . 但是只使用只读闭包,你至少可以实现Python提供语法糖的function decorator pattern .
Update
正如已经指出的那样,有一些方法可以处理python的范围限制,我将揭露一些 .
1. 使用
global
关键字(一般不推荐) .2. 定义一个简单的可修改类
Object
并在
initCounter
内创建一个Object scope
来存储变量由于
scope
实际上只是一个引用,因此对其字段执行的操作并不会真正修改scope
本身,因此不会出现错误 .3. 正如@unutbu指出的那样,另一种方法是将每个变量定义为一个数组(
x = [0]
)并修改它的第一个元素(x[0] += 1
) . 同样不会出现错误,因为x
本身未被修改 .4. 根据@raxacoricofallapatorius的建议,你可以使
x
成为counter
的属性我有一种情况,我需要一个单独但持久的名称空间 . 我上了课 . 我不这样做 . 隔离但持久的名称是闭包 .
我想在python和JS示例之间提供另一个简单的比较,如果这有助于使事情更清楚 .
JS:
并执行:
蟒蛇:
并执行:
Reason: 如上所述,在python中,如果内部作用域中的赋值具有相同名称的变量,则会在内部作用域中创建一个新引用 . JS不是这样,除非您使用
var
关键字明确声明一个 .