Python3学习笔记(十二):闭包
闭包定义:
在一个外函数中定义了一个内函数,内函数里引用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
我们先来看一个简单的函数:
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学习笔记(十二):闭包的更多相关文章
- python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL
python3.4学习笔记(十二) python正则表达式的使用,使用pyspider匹配输出带.html结尾的URL实战例子:使用pyspider匹配输出带.html结尾的URL:@config(a ...
- Go语言学习笔记十二: 范围(Range)
Go语言学习笔记十二: 范围(Range) rang这个关键字主要用来遍历数组,切片,通道或Map.在数组和切片中返回索引值,在Map中返回key. 这个特别像python的方式.不过写法上比较怪异使 ...
- Python学习笔记(十二)—Python3中pip包管理工具的安装【转】
本文转载自:https://blog.csdn.net/sinat_14849739/article/details/79101529 版权声明:本文为博主原创文章,未经博主允许不得转载. https ...
- java jvm学习笔记十二(访问控制器的栈校验机制)
欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 本节源码:http://download.csdn.net/detail/yfqnihao/4863854 这一节,我们 ...
- (C/C++学习笔记) 十二. 指针
十二. 指针 ● 基本概念 位系统下为4字节(8位十六进制数),在64位系统下为8字节(16位十六进制数) 进制表示的, 内存地址不占用内存空间 指针本身是一种数据类型, 它可以指向int, char ...
- JavaScript权威设计--命名空间,函数,闭包(简要学习笔记十二)
1.作为命名空间的函数 有时候我们需要声明很多变量.这样的变量会污染全局变量并且可能与别人声明的变量产生冲突. 这时.解决办法是将代码放入一个函数中,然后调用这个函数.这样全局变量就变成了 局部变量. ...
- ROS学习笔记十二:使用gazebo在ROS中仿真
想要在ROS系统中对我们的机器人进行仿真,需要使用gazebo. gazebo是一种适用于复杂室内多机器人和室外环境的仿真环境.它能够在三维环境中对多个机器人.传感器及物体进行仿真,产生实际传感器反馈 ...
- MySQL学习笔记十二:数据备份与恢复
数据备份 1.物理备份与逻辑备份 物理备份 物理备份就是将数据库的数据文件,配置文件,日志文件等复制一份到其他路径上,这种备份速度一般较快,因为只有I/O操作.进行物理备份时,一般都需要关闭mysql ...
- Java基础学习笔记十二 类、抽象类、接口作为方法参数和返回值以及常用API
不同修饰符使用细节 常用来修饰类.方法.变量的修饰符 public 权限修饰符,公共访问, 类,方法,成员变量 protected 权限修饰符,受保护访问, 方法,成员变量 默认什么也不写 也是一种权 ...
- Python3学习笔记十八
1. MTV M: model 与数据库相关 T: Template 与html相关 V: views 与逻辑相关 一. URL配置 启动:python ...
随机推荐
- Luogu P4436 [HNOI/AHOI2018]游戏
题目 我们要求出\(l_i,r_i\)表示\(i\)最远能够到达的最左边和最右边的格子. 首先有一个比较简单的暴力,就是每次我们选择一个格子,然后从当前格子开始往左右暴力扩展,找到能够到达的最远的格子 ...
- mysql开启和关闭安全模式
今天在进行数据库UPDATE的时候出了一个问题,我把非主键的字段当作UPDATE的条件(筛选条件)时,提示了如下的语句 Error Code: 1175. You are using safe upd ...
- python_0基础开始_day06
第六节 1.小数据池 ==,is,id ==:查看等号两边的值是否一样 a = 9b = 9print(a == b) # 返回Truec = "dog"d = "dog ...
- SVN服务器搭建与配置管理
1.下载和搭建SVN服务器 现在Subversion已经迁移到Apache网站上了,下载地址:http://subversion.apache.org/packages.html,这是二进制文件包的下 ...
- Java小程序—录屏小程序(下半场)
下半场. 上半场,我们我们写了录屏的程序,那么下半场我们的任务是写一个播放器. 设计思路:播放器的思路就是将图片放在一个JScrollPane中顺序播放,所以还是得使用swing组件,并且仍然要使用线 ...
- Codeforces 1196E. Connected Component on a Chessboard
传送门 注意到棋盘可以看成无限大的,那么只要考虑如何构造一个尽可能合法的情况 不妨假设需要的白色格子比黑色格子少 那么容易发现最好的情况之一就是白色排一排然后中间黑的先连起来,剩下黑色的再全部填白色周 ...
- linux centos 安装mongoDB
1.下载mongoDB 例如下载3.2.19 64位版本 https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-3.2.19.tgz ...
- 前端Ajax通过设置 timeout 参数,轮询后台API
因为我连接的数据库在台湾,相距较远,所以conn.Open()方法打开极慢.前端Ajax访问API时,API的数据还未返回,前端Ajax访问已经超时. 所以设置一个轮询,设置相隔多少秒之后进行一次查询 ...
- 动态表和C++ vector
动态表和C++ vector 最近课上刚刚学了可以根据表中元素的插入和删除动态调整表大小的动态表(dynamic table),就想看一下它有什么实际的应用,第一个想起来的就是C++的vector,直 ...
- new angular 项目的工作区配置文件和应用源文件
1.工作区配置文件 每个工作空间中的所有项目共享同一个 CLI 配置环境 .该工作空间的顶层包含着全工作空间级的配置文件.根应用的配置文件以及一些包含根应用的源文件和测试文件的子文件夹. 工作空间配置 ...