闭包定义:

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

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

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. idea 新建maven项目时,避免每次都需要指定自己的maven目录

    01 .File->Other Settings -> Settings for New Project 02. 将Maven home directory目录修改成我们自己安装Maven ...

  2. 牛客 545C 出题人的数组 (贪心)

    出题人有两个数组A,B,请你把两个数组归并起来使得$cost=\sum i c_i$最小. 归并要求原数组的数的顺序在新数组中不改变. 贪心水题 对于一段序列$A_i,A_{i+1},...,A_r$ ...

  3. 使用parquet-hadoop.jar包解析hive parquet文件时,遇到FIXED_LEN_BYTE_ARRAY转换为Decimal 以及 INT96转换为timestamp问题

    在使用parquet-hadoop.jar包解析parquet文件时,遇到decimal类型的数据为乱码,具体解决方法如下: 使用parquet-Hadoop.jar解析httpfs服务提供的parq ...

  4. ftp服务器上传下载共享文件

    1 windows下搭建ftp服务器 https://blog.csdn.net/qq_34610293/article/details/79210539 搭建好之后浏览器输入 ftp://ip就可以 ...

  5. django自带登录认证与登录自动跳转

    # 导入django自带模块 from django.contrib.auth import authenticate, login, logout # 使用authenticate进行认证,使用lo ...

  6. mysql-8.0.17-winx64 部署

    1.官网下载mysql-8.0.17-winx64,选择Zip文件格式下载 2.解压到目标路径,我这里是E盘根目录,即E:\mysql8 3.根目录下创建my.ini,内容如下: [mysqld]#端 ...

  7. window.prompt()和 window.confirm()选择

    代码截图: 效果:  代码截图: 效果:

  8. N4语法

    第一期  授受关系 这里讲的授受关系是指“物的收受”也就是前后两个主体之前的“物的收受”. 请看以下三个基本句型:(从接收者B来分析) 1. AはBに-を         あげる(平辈.晚辈) (A给 ...

  9. RHEL6中LVM逻辑卷管理

    1.LVM 基本术语   物理卷(physical volume):物理卷在逻辑卷管理中处于最底层,它可以是实际物理硬盘上的分区,也可以是整个物理硬盘.   卷组(Volume Group):卷组建立 ...

  10. 修改linux系统TCP连接数

    修改linux系统TCP连接数 centOS 6.x (1)vi /etc/sysctl.conf (2)添加参数 net.nf_conntrack_max = 655360 (3)sysctl -p ...