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 ...
随机推荐
- c++学习之对象和类——构造函数和析构函数
再认真理一遍~ 0.类 这里先来定义一个类,便于后面的理解.参考C++ Primer Plus class Stock { private: std::string company; long sha ...
- python基础数据类型之一
python属于解释型(有良好的平台兼容性,在任何环境中都可以运行,修改代码的时候直接修改就可以,可以快速部署,不用停机维护).动态的(python在编程之前不需要提前设定好各种变量,C语言之类的需要 ...
- L2Dwidget.js L2D网页动画人物添加
hexo 添加live2d看板动画 https://www.jianshu.com/p/3a6342e16e57 首先贴出官网代码 官网地址配置:https://www.npmjs.com/packa ...
- 微软商店(Microsoft store)删除之后恢复,一行代码搞定
首先以管理员身份运行Windows PowerShell 地址C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\P ...
- 测试Random类nextInt()方法连续两次结果一样的概率
public static void main(String[] args) { int count = 0; int a = 0; Random r = new Random(); while (t ...
- 深入理解并使用python的模块与包
模块 编写好的一个python文件可以有两种用途:1)脚本,一个文件就是整个程序,用来被执行2)模块,文件中存放着一堆功能,用来被导入使用 模块的分类 1)开发者编写的 .py文件2 ) 由C或C++ ...
- MySQL5.5配置文件my.ini详解
[client]port = 3306 [mysqld]port = 3306 ##安装目录 basedir="C:/Program Files (x86)/MySQL/MySQL Serv ...
- 00:Java简单了解
浅谈Java之概述 Java是SUN(Stanford University Network),斯坦福大学网络公司)1995年推出的一门高级编程语言.Java是一种面向Internet的编程语言.随着 ...
- spring中对JDO的配置
<!-- persistenceManagerFactory --> <bean id="myPmf" class="org.springframewo ...
- 白盒测试之JUnit与SpringTest的完美结合
通过白盒的单元测试可以验证程序基本功能的有效性,从而保证整个系统的质量,功在一时,利在千秋.目前80%以上公司后台还是基于java,尤其是后台大量采用Spring框架,我们这里采用Junit和Spri ...