python闭包的详细解析
一、什么是闭包?
如果一个内嵌函数访问外部嵌套函数作用域的变量,并返回这个函数,则这个函数就是闭包
闭包必须满足三个条件:
1. 必须有一个内嵌函数
2. 内嵌函数必须引用外部嵌套函数中的变量
3. 外部函数返回值必须是内嵌函数
闭包的特点:
一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。
很晦涩很难理解啊~我们来看一段代码^.^
#闭包函数的实例
2 # outer是外部函数 a和b都是外函数的临时变量
3 def outer( a ):
4 b = 10
5 # inner是内函数
6 def inner():
7 #在内函数中 用到了外函数的临时变量
8 print(a+b)
9 # 外函数的返回值是内函数的引用
10 return inner
11
12 if __name__ == '__main__':
13 # 在这里我们调用外函数传入参数5
14 #此时外函数两个临时变量 a是5 b是10 ,并创建了内函数,然后把内函数的引用返回存给了demo
15 # 外函数结束的时候发现内部函数将会用到自己的临时变量,这两个临时变量就不会释放,会绑定给这个内部函数
16 demo = outer(5)
17 # 我们调用内部函数,看一看内部函数是不是能使用外部函数的临时变量
18 # demo存了外函数的返回值,也就是inner函数的引用,这里相当于执行inner函数
19 demo() #
20
21 demo2 = outer(7)
22 demo2()#
复制代码
从上面例子是一个最简单的很典型的闭包。可能很多名词都不明白是什么意思,没关系,我们把这些名词去解释一下~
1 外函数返回了内函数的引用:
引用是什么?在python中一切都是对象,包括整型数据1,函数,其实是对象。
当我们进行a=1的时候,实际上在内存当中有一个地方存了值1,然后用a这个变量名存了1所在内存位置的引用,大家可以把引用理解成地址。a只不过是一个变量名字,a里面存的是1这个数值所在的地址,就是a里面存了数值1的引用。
相同的道理,当我们在python中定义一个函数def demo(): 的时候,内存当中会开辟一些空间,存下这个函数的代码、内部的局部变量等等。这个demo只不过是一个变量名字,它里面存了这个函数所在位置的引用而已。我们还可以进行x = demo, y = demo, 这样的操作就相当于,把demo里存的东西赋值给x和y,这样x 和y 都指向了demo函数所在的引用,在这之后我们可以用x() 或者 y() 来调用我们自己创建的demo() ,调用的实际上根本就是一个函数,x、y和demo三个变量名存了同一个函数的引用。
有了上面的解释,我们可以继续说,返回内函数的引用是怎么回事了。对于闭包,在外函数outer中 最后return inner,我们在调用外函数 demo = outer() 的时候,outer返回了inner,inner是一个函数的引用,这个引用被存入了demo中。所以接下来我们再进行demo() 的时候,相当于运行了inner函数。
所以,一个函数,如果函数名后紧跟一对括号,相当于现在我就要调用这个函数,如果不跟括号,相当于只是一个函数的名字,里面存了函数所在位置的引用。
2 外函数把临时变量绑定给内函数:
按照我们正常的认知,一个函数结束的时候,会把自己的临时变量都释放还给内存,之后变量都不存在了。一般情况下,确实是这样的。但是闭包是一个特别的情况。外部函数发现,自己的临时变量会在将来的内部函数中用到,自己在结束的时候,返回内函数的同时,会把外函数的临时变量送给内函数绑定在一起。所以外函数已经结束了,调用内函数的时候仍然能够使用外函数的临时变量。
在我编写的实例中,我两次调用外部函数outer,分别传入的值是5和7。内部函数只定义了一次,我们发现调用的时候,内部函数是能识别外函数的临时变量是不一样的。python中一切都是对象,虽然函数我们只定义了一次,但是外函数在运行的时候,实际上是按照里面代码执行的,外函数里创建了一个函数,我们每次调用外函数,它都创建一个内函数,虽然代码一样,但是却创建了不同的对象,并且把每次传入的临时变量数值绑定给内函数,再把内函数引用返回。虽然内函数代码是一样的,但其实,我们每次调用外函数,都返回不同的实例对象的引用,他们的功能是一样的,但是它们实际上不是同一个函数对象。
3 闭包中内函数修改外函数局部变量:
在闭包内函数中,我们可以随意使用外函数绑定来的临时变量,但是如果我们想修改外函数临时变量,就要用专门的关键字了!
详细解决方案请参考上一篇博客!
还有一点需要注意:使用闭包的过程中,一旦外函数被调用一次返回了内函数的引用,虽然每次调用内函数,是开启一个函数执行过后消亡,但是闭包变量实际上只有一份,每次开启内函数都在使用同一份闭包变量
上代码!

1 #coding:utf8
2 def outer(x):
3 def inner(y):
4 nonlocal x
5 x+=y
6 return x
7 return inner
8
9
10 a = outer(10)
11 print(a(1)) //11
12 print(a(3)) //14

两次分别打印出11和14,由此可见,每次调用inner的时候,使用的闭包变量x实际上是同一个。
二、闭包有啥用?
很多伙伴很糊涂,闭包有啥用啊?
装饰器!!详细解析请参考上上篇博客!
python闭包的详细解析的更多相关文章
- python lambda函数详细解析(面试经常遇到)
1 作用:通常是用来在python中创建匿名函数的 2 格式: lambda 参数[,参数] : 表达式 3 注意: (1)lambda定义的是单行函数, 如果需要复杂的函数,应该定义普通函数 (2) ...
- 【转】python中的闭包详细解析
一.什么是闭包? 如果一个内嵌函数访问外部嵌套函数作用域的变量,并返回这个函数,则这个函数就是闭包 闭包必须满足三个条件: 1. 必须有一个内嵌函数 2. 内嵌函数必须引用外部嵌套函数中的变量 ...
- Python闭包详解
Python闭包详解 1 快速预览 以下是一段简单的闭包代码示例: def foo(): m=3 n=5 def bar(): a=4 return m+n+a return bar >> ...
- Python闭包及其作用域
Python闭包及其作用域 关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记 如果在一个内部函数里,对一个外部作用域(但不是全局作用域 ...
- Python 闭包小记
闭包就是能够读取其他函数内部变量的函数.例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“.在本质上,闭包是将函数内部和函数外部连接起来 ...
- 理解Python闭包概念
闭包并不只是一个python中的概念,在函数式编程语言中应用较为广泛.理解python中的闭包一方面是能够正确的使用闭包,另一方面可以好好体会和思考闭包的设计思想. 1.概念介绍 首先看一下维基上对闭 ...
- python 闭包和装饰器
python 闭包和装饰器 一.闭包闭包:外部函数FunOut()里面包含一个内部函数FunIn(),并且外部函数返回内部函数的对象FunIn,内部函数存在对外部函数的变量的引用.那么这个内部函数Fu ...
- Thrift之代码生成器Compiler原理及源码详细解析2
我的新浪微博:http://weibo.com/freshairbrucewoo. 欢迎大家相互交流,共同提高技术. 2 t_generator类和t_generator_registry类 这个两 ...
- Thrift之代码生成器Compiler原理及源码详细解析1
我的新浪微博:http://weibo.com/freshairbrucewoo. 欢迎大家相互交流,共同提高技术. 又很久没有写博客了,最近忙着研究GlusterFS,本来周末打算写几篇博客的,但是 ...
随机推荐
- JQuery miniui使用小记
1.renderer="onActionRenderer" 如我们需要在一行数据时加上删除操作时,就需要在每行上加上“删除”按钮,以下为实现代码: 列加载时主要的属性
- jquery如何实现当页面下拉到一定位置时,右下角出现回到顶部图标
渐进式返回顶部
- leetcode2
/** * Definition for singly-linked list. * public class ListNode { * public int val; * public ListNo ...
- Django之model联表:一对多、跨表操作,联表查询
表结构概述 model.py : class Something(models.Model): name = models.CharField(max_length=32) class UserTyp ...
- 第四篇、Python文件处理
1.文件操作 1) 文件操作流程 a. 打开文件,得到文件句柄并赋值给一个变量 b. 通过句柄对文件进行操作 c. 关闭文件 f=open('a.txt','r',encoding='utf-8') ...
- Install weblogic in silent mode
使用静默(silent)模式来安装weblogic,在需要将安装脚本化,或无法使用图形界面的时候非常有用. 下面按照自己在实际工作中碰到的例子,来慢慢总结不同版本和平台weblogic的静默安装方法. ...
- 云笔记项目-Java反射知识学习
在云笔记项目中,补充了部分反射的知识,反射这一部分基础知识非常重要,前面学习的框架Spring和MyBatis读取xml配置文件创建对象,以及JDBC加载驱动等都用了反射,但只知道有这个东西,具体不知 ...
- C程序的编译与链接
编译器驱动程序 编译器驱动程序可以在用户需要时调用语言预处理器.编译器.汇编器和链接器. 例如使用GNU编译系统,我们需要使用如下命令来调用GCC驱动程序: gcc -o main main.c 编译 ...
- 纯css loading动效
.loading {margin: 100px; width: 3px; height:3px; border-radius: 100%; / ...
- Es6(Symbol,set,map,filter)
首先再讲这几个新东西之前,先说一个Es6中新出的扩展运算符(...) 1.展开运算符,就是把东西展开,可以用在array和object上 比如: let a=[,] let b=[,...a,]//[ ...