英文称之为Closure,中文译为闭包,闭包的概念也并不是Python独有的,Javascript等高级语言中也存在闭包的概念。那什么是闭包?有一个经典的公式可以回答这个问题:

闭包 = 内部函数 + 引用环境

这个公式非常清楚地说明,闭包本质上是具备"封闭"上下文环境的函数。所谓"封闭",是说该函数的上下文环境不会随着函数调用结束而销毁,实际上会持久驻留内存。众所周知,函数通常定义在全局上下文,而闭包函数定义在函数内部,全局上下文也是持久驻留的,把函数定义在全局上下文中也可以有相同效果,那闭包有什么不一样的地方?答案是可以避免全局变量的污染。

接下来,我们从简单闭包开始,逐步探讨下闭包的使用。

1、简单闭包

首先最简单的闭包是外部函数只传递一个函数引用和内部函数不带参数的闭包。我们在Pycharm中演示下简单闭包:

在上图的代码中,有以下几个关键点:

  1. 定义一个outer_func,outer_func的参数为一个函数引用func;
  2. 在outer_func中定义inner_func,并返回inner_func的引用;
  3. inner_func调用outer_func中传递的func引用的函数;
  4. 全局定义一个没有参数的print_info函数;
  5. 通过outer_func(print_info)得到f,此时的f指向outer_func中的inner_func已用
  6. 调用函数f

运行结果为:

通过简单闭包的演示可以看出,闭包中的引用环境主要是外部函数的变量,包括外部函数参数和外部函数中定义的变量,这个闭包在整个运行环境中,外部函数的参数和变量是一直被"锁"在内存中的,这也是调用f时还能访问func的原因。

当然,实际应用中func不可能没有参数,接下来让我们分析下带参数的闭包。

2、带参闭包

所谓带参闭包,是指闭包函数可以带参数,也就是上节中的inner_func可以带参数。我们在Pycharm演示下:

运行结果:

通过增加info,可以让闭包传递参数,稍有经验的开发者一眼就能看出这种带不可变参数的闭包不够通用,因为不可能参数增加一个就再定义一个闭包。在Python中,一旦涉及可变参数,需要使用_args和**kwargs,好了,我们用_args和**kwargs改造下上面的闭包:

运行结果:

3、闭包隔离

前面两节中,我们定义完闭包后,在使用过程中只创建了一个闭包函数,现在我们在Pycharm中做如下实验:

运行结果:

要提一下的是,在outer_func中定义了count,如果在inner_func只是读取count的话直接使用count即可,如果在inner_func中要写count,则需要在inner_func中声明nonlocal,与普通函数中修改全局变量时使用global类似,只不过nonlocal修饰的变量是外部函数中的变量。在本实验中,使用outer_func(print_info)定义两个"相同"的闭包f1和f2,f1调用3次,f2调用1次,从运行结果来看f1中的count虽然增加了,但是并不影响f2中的count,这说明了闭包一个很重要的特点:内存隔离。也就是说两个闭包函数的引用环境是独立的,彼此不影响,就像类的实例对象一样。

4、结尾

经过前面三节的分析之后,我们再回顾下闭包概念的经典公式:

闭包 = 内部函数 + 引用环境

可以简单总结下:

  1. 闭包是定义在一个函数内部的函数;

  2. 外部函数传递一个函数引用给内部函数,并返回内部函数引用;

  3. 内部函数可以访问外部函数的变量,并调用外部函数传递的函数引用;

  4. 闭包之间内存隔离

---------------------------END---------------------------

题外话

感谢你能看到最后,给大家准备了一些福利!

感兴趣的小伙伴,赠送全套Python学习资料,包含面试题、简历资料等具体看下方。


👉CSDN大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。

img

二、Python兼职渠道推荐*

学的同时助你创收,每天花1-2小时兼职,轻松稿定生活费.
在这里插入图片描述

三、最新Python学习笔记

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。

img

四、实战案例

纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

img

👉CSDN大礼包🎁:全网最全《Python学习资料》免费赠送🆓!(安全链接,放心点击)

若有侵权,请联系删除

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐