闭包定义:

在一个外函数中定义了一个内函数,内函数里引用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。

我们先来看一个简单的函数:

def outer(a):
b = 10
print(a+b)

这个函数定义了一个局部变量b,我们来调用这个函数看一下

>>> outer(5)
15
>>> print(b)
Traceback (most recent call last):
File "<pyshell#42>", line 1, in <module>
print(b)
NameError: name 'b' is not defined

可以看到在调用完函数outer后,再打印变量b时,会报变量b没定义。这个我们很容易理解:b是函数outer的一个局部变量,调用函数结束后,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。

我们再来看一个嵌套函数:

def outer(a):
b = 10
def inner():
print(a+b)
return inner

这个函数的返回值是一个函数对象,也就是inner函数,我们来调用下这个函数

>>> demo = outer(5)      # 返回的是inner函数
>>> demo() # 这里就相当于执行inner()
15

看到这里是不是感觉到有点奇怪,执行demo = outer(5)后,就是调用outer函数结束了,按道理说这个时候outer函数内的所有东西都会释放掉,包括局部变量a,b。那么为什么我在执行demo()时,还可以打印出a+b的值呢?

这就是一种特殊情况,按照文章开始处闭包的定义,这个嵌套函数其实就是一个闭包,它有一种特权:如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。

我们知道什么是闭包了,也知道在闭包中外函数会把变量绑定到内函数上,那么在内函数中能不能修改外函数的变量呢?

我们来试一下:

def outer(a):
b = 10
def inner():
b += 1
print(b)
return inner

调用:

>>> demo = outer(5)
>>> demo()
Traceback (most recent call last):
File "<pyshell#47>", line 1, in <module>
demo()
File "C:\Users\lmj\AppData\Local\Programs\Python\Python36\1.py", line 4, in inner
b += 1
UnboundLocalError: local variable 'b' referenced before assignment

报错,看来是不能直接修改,得想其他办法。

在函数作用域中,我们知道如果要在函数中修改全局变量,有两种方法:

  • global 声明全局变量
  • 全局变量是可变数据类型

同样,在闭包中也是类似情况,在内函数中想修改外函数绑定到内函数的变量时,也有两种方法:

  • 用nonlocal 关键字声明 一个变量, 表示这个变量不是局部变量空间的变量,需要向上一层变量空间找这个变量。
  • 把外函数变量改成可变类型数据进行修改
def outer(a):
b = 10
c = [a] # 把外函数变量修改成列表
def inner():
nonlocal b # nonlocal声明外函数变量
b += 1
c[0] += 1
print(b)
print(c[0])
return inner

调用:

>>> demo = outer(5)
>>> demo()
11
6

Python3学习笔记(十二):闭包的更多相关文章

  1. python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL

    python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL实战例子:使用pyspider匹配输出带.html结尾的URL:@config(a ...

  2. Go语言学习笔记十二: 范围(Range)

    Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...

  3. Python学习笔记(十二)—Python3中pip包管理工具的安装【转】

    本文转载自:https://blog.csdn.net/sinat_14849739/article/details/79101529 版权声明:本文为博主原创文章,未经博主允许不得转载. https ...

  4. java jvm学习笔记十二(访问控制器的栈校验机制)

    欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 本节源码:http://download.csdn.net/detail/yfqnihao/4863854 这一节,我们 ...

  5. (C/C++学习笔记) 十二. 指针

    十二. 指针 ● 基本概念 位系统下为4字节(8位十六进制数),在64位系统下为8字节(16位十六进制数) 进制表示的, 内存地址不占用内存空间 指针本身是一种数据类型, 它可以指向int, char ...

  6. JavaScript权威设计--命名空间,函数,闭包(简要学习笔记十二)

    1.作为命名空间的函数 有时候我们需要声明很多变量.这样的变量会污染全局变量并且可能与别人声明的变量产生冲突. 这时.解决办法是将代码放入一个函数中,然后调用这个函数.这样全局变量就变成了 局部变量. ...

  7. ROS学习笔记十二:使用gazebo在ROS中仿真

    想要在ROS系统中对我们的机器人进行仿真,需要使用gazebo. gazebo是一种适用于复杂室内多机器人和室外环境的仿真环境.它能够在三维环境中对多个机器人.传感器及物体进行仿真,产生实际传感器反馈 ...

  8. MySQL学习笔记十二:数据备份与恢复

    数据备份 1.物理备份与逻辑备份 物理备份 物理备份就是将数据库的数据文件,配置文件,日志文件等复制一份到其他路径上,这种备份速度一般较快,因为只有I/O操作.进行物理备份时,一般都需要关闭mysql ...

  9. Java基础学习笔记十二 类、抽象类、接口作为方法参数和返回值以及常用API

    不同修饰符使用细节 常用来修饰类.方法.变量的修饰符 public 权限修饰符,公共访问, 类,方法,成员变量 protected 权限修饰符,受保护访问, 方法,成员变量 默认什么也不写 也是一种权 ...

  10. Python3学习笔记十八

    1.    MTV M:   model     与数据库相关 T:   Template    与html相关 V:   views      与逻辑相关 一.    URL配置 启动:python ...

随机推荐

  1. ASP.NET Core中使用EasyCaching作为缓存抽象层

    ⒈是什么? 和CacheManager差不多,两者的定位和功能都差不多. EasyCaching主要提供了下面的几个功能 统一的抽象缓存接口 多种常用的缓存Provider(InMemory,Redi ...

  2. springboot笔记-使用JSP

    Spring Boot 项目中使用 JSP: 项目结构:需要添加webapp文件夹用来存放目录 jsp 文件 spring-boot-jsp +-src +- main +- java +- reso ...

  3. POJ - 3469 Dual Core CPU (最小割)

    (点击此处查看原题) 题意介绍 在一个由核A和核B组成的双核CPU上执行N个任务,任务i在核A上执行,花费Ai,在核B上执行,花费为Bi,而某两个任务之间可能需要进数据交互,如果两个任务在同一个核上执 ...

  4. session的垃圾回收机制

    session.gc_maxlifetime session.gc_probability session.gc_divisor session.gc_divisor 与 session.gc_pro ...

  5. mysql-1.1基础

    笔记内容:mysql基础,创建数据库,创建表,操作数据表,操作数据,简单查询,条件查询,排序,分组,聚合,连接查询(等值连接,内连接,外链接),子查询 自己提示:脑图笔记存于网盘中  右键:新标签页打 ...

  6. 链接校验——是否是协议http://或https://开头的

    if(str.substr(0,7)!="http://" && str.substr(0,7)!="https://"){ return 'y ...

  7. 06 Django之模型层---多表操作

    一 创建模型 表和表之间的关系 一对一.多对一.多对多 ,用book表和publish表自己来想想关系,想想里面的操作,加外键约束和不加外键约束的区别,一对一的外键约束是在一对多的约束上加上唯一约束. ...

  8. 原生JS+CSS实现日期插件

    笔者最近在学习Element UI,觉得它提供的日期选择器既简单又美观,于是仿照着写了一个日期插件.笔者使用到的技术有ES5.CSS和HTML,控件兼容IE10+和谷歌浏览器.有一点需要注意,笔者使用 ...

  9. pycharm terminal打开在虚拟环境

    pycharm调试是虚拟环境,terminal不是虚拟环境,搞了好久,原来需要激活一下 cd   venv\Scripts> 去虚拟环境的Script目录下,运行activate.bat激活环境 ...

  10. 原生javascript的意义

    原生JS是指遵循ECMAscript标准的javascript,不同于微软的jscript也不依赖于任何框架,依托于浏览器标准引擎的脚本语言. jquery是在原生态的js上集成的框架资源,使用jqu ...