Python闭包之一

来源:互联网 发布:怎么才能做淘宝直播 编辑:程序博客网 时间:2024/06/11 04:39

1.引言

最近在学习Python中的闭包,愿与大家共同分享我的学习感悟。

本文现以下面这个简单的例子来开始对Python里面闭包的探究,这个例子的代码如下:


运行这个小模块得到结果如下:


看到这里,你可能悟到了一些东西,对于闭包也或许有了一些想法,接着,我将上面的文件做一个小小的改动,改动后 的文件如下:

想必大家能够猜的到结果,再次运行这个文件,得到如下结果:


下面我开始对Python中的闭包做一个简单的讲解(仅仅是我的学习感悟或者说是我的理解),首先,我们来看一个闭包的具体应用的例子,在Python中叫做(函数)装饰器 。

2.装饰器

什么是装饰器呢?
从语法上来讲,函数装饰器是它后面的函数的运行时的声明。函数装饰器是写成一行,就在定义函数或者方法的def语句之前,而且由@符号,后面跟着所谓的元函数(metafunction)组成:也就是管理另一函数(或其他可调用对象)的函数。
通俗地讲,即我的理解是:装饰器的功能是将被装饰的函数当作参数传递给与装饰器相对应的函数(名称相同的函数),并返回包装后的被装饰的函数,看个示意图,其中a为与装饰器@a对应的函数,b为装饰器修饰的函数:

举个例子:

上面使用@d来表示装饰器,其等同于:q=d(q) 因此装饰器本质上就是个语法糖,其作用为简化代码,以提高代码可读性,运行上段代码的结果为:

解析过程是这样子的:
1.python解释器发现@d,就去调用与其对应的函数(d函数)
2.d函数调用前要指定一个参数,传入的就是@d下面修饰的函数,也就是q()
3.d()函数执行,调用q(),q()打印“d”
现在来解释什么是闭包。

3.闭包

首先还得从基本概念说起,什么是闭包呢?来看下维基上的解释:

在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。
上面提到了两个关键的地方: 自由变量 和 函数, 这两个关键稍后再说。还是得在赘述下“闭包”的意思,望文知意,可以形象的把它理解为一个封闭的包裹,这个包裹就是一个函数,当然还有函数内部对应的逻辑,包裹里面的东西就是自由变量,自由变量可以在随着包裹到处游荡。当然还得有个前提,这个包裹是被创建出来的。
在通过Python的语言介绍一下,一个闭包就是你调用了一个函数A,这个函数A返回了一个函数B给你。这个返回的函数B就叫做闭包。你在调用函数A的时候传递的参数就是自由变量。

举例如下:


这里面调用func的时候就产生了一个闭包——inner_func,并且该闭包持有自由变量——name,因此这也意味着,当函数func的生命周期结束之后,name这个变量依然存在,因为它被闭包引用了,所以不会被回收。
另外再说一点,闭包并不是Python中特有的概念,所有把函数做为一等公民的语言均有闭包的概念。不过像Java这样以class为一等公民的语言中也可以使用闭包,只是它得用类或接口来实现。

4.装饰器与闭包

本文前面提到过装饰器就是一种的闭包的应用,只不过其传递的是函数,来看下面的例子:


运行上述代码可得结果如下:


@makeitalic装饰器将函数hello传递给函数makeitalic,函数makeitalic执行完毕后返回被包装后的hello函数,而这个过程其实就是通过闭包实现的。@makebold也是如此,只不过其传递的是@makeitalic装饰过的hello函数,因此最后的执行结果<b>在<i>外层,这个功能如果不用装饰器,其实就是显式的使用闭包:


5.闭包的作用

闭包的最大特点是可以将父函数的变量与内部函数绑定,并返回绑定变量后的函数(也即闭包),此时即便生成闭包的环境(父函数)已经释放,闭包仍然存在,这个过程很像类(父函数)生成实例(闭包),不同的是父函数只在调用时执行,执行完毕后其环境就会释放,而类则在文件执行时创建,一般程序执行完毕后作用域才释放,因此对一些需要重用的功能且不足以定义为类的行为,使用闭包会比使用类占用更少的资源,且更轻巧灵活,现举一例:假设我们仅仅想打印出各类动物的叫声,分别以类和闭包来实现:


运行结果如下:


可以看到输出结果是完全一样的,但显然类的实现相对繁琐,且这里只是想输出一下动物的叫声,定义一个Animal类未免小题大做,而且voice函数在执行完毕后,其作用域就已经释放,但Animal类及其实例dog的相应属性却一直贮存在内存中,而这种占用对于实现该功能后,则是没有必要的。

除此之外,闭包还有很多其他功能,比如用于封装等,另外,闭包有效的减少了函数参数的数目,这对并行计算非常有价值,比如可以让每台电脑负责一个函数,然后串起来,实现流水化的作业等。

0 0
原创粉丝点击