python编程思想-闭包

什么是闭包(Closure)?

先看看wiki百科是怎么解释的:

In programming languages, a closure(also lexical closure or function closure) is a technique for implementing lexically scoped name binding in a language with first-class functions. Operationally, a closure is a record storing a function together with an environment. The environment is a mapping associating each free variable of the function (variables that are used locally, but defined in an enclosing scope) with the value or reference to which the name was bound when the closure was created. A closure (unlike a plain function) allows the function to access those captured variables through the closure’s copies of their values or references, even when the function is invoked outside their scope.

之我见:我们一般说起将属性方法进行封装就会想到闭包的作用类似于,只是它的专能性似乎更强。

用栗子来解释闭包为什么会和相似:

1
2
3
4
5
6
def closure_def(x):
y = 1
z = 2
def fn():
print((x+y)*z)
return fn

对于上面这个简单的栗子,我们发现以下几个特点:

  1. yz 是函数 closure_def 作用域下的局部变量
  2. 函数 fn 定义在 函数 closure_def 的内部,同时它将直接调用 yz
  3. 函数 closure_def返回的是函数 fn 的引用

我们获取一个闭包

1
2
3
closure_1 = closure_def(4)
closure_1()
#输出结果为 10

上述的 closure_1 就是传说中的闭包。因此,闭包本质上还是一个函数,我们通过 closure_1() 调用这个函数后将会输出结果10.

其实到这里我还是没弄清楚闭包到底相似在哪里。但是,这里有个很有意思的东西:我们通过 closure_def(4) 调用了闭包定义函数后,该函数内的局部变量(yz)应该就失效了,但是函数fn实际上却被我们保存了下来(在closure_1中)。然而,这个closure_1需要使用yz,按照我们前面的逻辑,这两个变量已经失效了,这就产生了一个十分尴尬的问题。

真实情况并非这样,yz变量明显还存在于内存中,并且它们与这个fn函数绑定在一起了。这就是闭包的特性:将yz这两个变量和函数fn绑定在一起,就好比中将属性方法绑定一样。

在python中,函数同基本数据类型一样同属于一级类对象,函数名就是这个一级类实例的引用。对于闭包,函数需要用到的变量值实际上存在于其中,我们可以这样访问这些变量:

  • .__closure__ 返回一组存有变量值的cell对象
  • .__closure__[0].cell_centents 将获取相应变量的值

从上面我们发现,闭包就是将一组变量和一个函数进行封装,如下所示:

我们保存的只有蓝色框框部分,但是蓝色框框需要使用红色框框内的变量,闭包就将这两个框框进行封装。橙色框框返回闭包中的那个主函数。

而且,当我们只是对一个函数进行简单的封装(修饰)时,使用闭包将更加优雅

闭包的一个重要应用就是python的装饰器(Decorator),且等下回之我见。

----- For reprint please indicate the source -----
0%