一、什么是闭包?

如果一个内嵌函数访问外部嵌套函数作用域的变量,并返回这个函数,则这个函数就是闭包

闭包必须满足三个条件:

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闭包的详细解析的更多相关文章

  1. python lambda函数详细解析(面试经常遇到)

    1 作用:通常是用来在python中创建匿名函数的 2 格式: lambda 参数[,参数] : 表达式 3 注意: (1)lambda定义的是单行函数, 如果需要复杂的函数,应该定义普通函数 (2) ...

  2. 【转】python中的闭包详细解析

    一.什么是闭包? 如果一个内嵌函数访问外部嵌套函数作用域的变量,并返回这个函数,则这个函数就是闭包 闭包必须满足三个条件: 1. 必须有一个内嵌函数    2. 内嵌函数必须引用外部嵌套函数中的变量  ...

  3. Python闭包详解

    Python闭包详解 1 快速预览 以下是一段简单的闭包代码示例: def foo(): m=3 n=5 def bar(): a=4 return m+n+a return bar >> ...

  4. Python闭包及其作用域

    Python闭包及其作用域 关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记 如果在一个内部函数里,对一个外部作用域(但不是全局作用域 ...

  5. Python 闭包小记

    闭包就是能够读取其他函数内部变量的函数.例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“.在本质上,闭包是将函数内部和函数外部连接起来 ...

  6. 理解Python闭包概念

    闭包并不只是一个python中的概念,在函数式编程语言中应用较为广泛.理解python中的闭包一方面是能够正确的使用闭包,另一方面可以好好体会和思考闭包的设计思想. 1.概念介绍 首先看一下维基上对闭 ...

  7. python 闭包和装饰器

    python 闭包和装饰器 一.闭包闭包:外部函数FunOut()里面包含一个内部函数FunIn(),并且外部函数返回内部函数的对象FunIn,内部函数存在对外部函数的变量的引用.那么这个内部函数Fu ...

  8. Thrift之代码生成器Compiler原理及源码详细解析2

    我的新浪微博:http://weibo.com/freshairbrucewoo. 欢迎大家相互交流,共同提高技术. 2  t_generator类和t_generator_registry类 这个两 ...

  9. Thrift之代码生成器Compiler原理及源码详细解析1

    我的新浪微博:http://weibo.com/freshairbrucewoo. 欢迎大家相互交流,共同提高技术. 又很久没有写博客了,最近忙着研究GlusterFS,本来周末打算写几篇博客的,但是 ...

随机推荐

  1. Node学习笔记(一)

    1. node的特点: Node.js 不是一种独立的语言,与 PHP.Python.Perl.Ruby 的“既是语言也是平台”不同.Node.js 也不是一个 JavaScript 框架,不同于 C ...

  2. http stream

    http stream 博客分类: http://canofy.iteye.com/blog/2097876 j2EE   StringBuilder sb = new StringBuilder() ...

  3. Linux环境变量设置/etc/profile、/etc/bashrc、~/.profile、~/.bashrc区别

    登入系统读取步骤: 当登入系统时候获得一个shell进程时,其读取环境设定档有三步 : 1.首先读入的是全局环境变量设定档/etc/profile,然后根据其内容读取额外的设定的文档,如 /etc/p ...

  4. python3 re.compile中含有变量

    id = '7F' reg = re.compile(id + '[^\dA-F]?\d') line = ‘122s 7f 3' match = reg.search(line) 在程序中有时候会遇 ...

  5. 4-29 c语言之栈,队列,双向链表

    今天学习了数据结构中栈,队列的知识 相对于单链表来说,栈和队列就是添加的方式不同,队列就相当于排队,先排队的先出来(FIFO),而栈就相当于弹夹,先压进去的子弹后出来(FILO). 首先看一下栈(St ...

  6. Python-反射getattr的应用

    login.py #!/usr/bin/dev python# coding:utf-8 def index(): print u'欢迎访问xx网站首页' def login(): print u'登 ...

  7. NetBeans 代码折叠

    代码折叠 // <editor-fold>   Your code goes here...// </editor-fold> 添加描述 // <editor-fold ...

  8. IOS搜索框输入中文解决方案(防抖)

    class Header extends React.Component { constructor(props) { super(props); this.time = 0; // 重点在于这个th ...

  9. mysql实用函数

    1.  group_concat(); 可以将选择的字段列数据,分组以逗号分隔成一串.实用方便.select id,group_concat(distinct name) from ttt group ...

  10. 解决:win10在空白处右键资源管理器重启的故障

    一,查看windows日志 win+R,输入eventvwr,打开事件查看器,展开左边Windows日志,双击圆形红底白色感叹号图标所在的行. 查找错误模块名称. 对比图标和名称,这是"飞鸽传书"的安 ...