深入浅出Python闭包
闭包简述
闭包概念:在一个内部函数中,对外部作用域的变量进行引用, (并且一般外部函数的返回值为内部函数),那么内部函数就被认为是闭包
(colsure)
。
函数引用
在Python中,万物皆对象,因此函数也不例外。函数的名称可以当做变量使用。来看看下面几个例子:
In [2]: def func1():...: print("func1() called")...:In [3]: type(func1)
Out[3]: functionIn [4]: func1
Out[4]: <function __main__.func1()># 函数引用赋值
In [5]: func = func1In [6]: id(func)
Out[6]: 1875091721816In [7]: id(func1)
Out[7]: 1875091721816# 函数调用
In [8]: func()
func1() calledIn [9]: func1()
func1() called
模拟事件处理范例
方案一、if判断
# -------------------- 函数引用的范例 -------------------- #
import randomdef onclick():"""点击事件处理"""print("onclick called")def onhover():"""悬浮事件处理"""print("onhover called")def onmove():"""移动事件处理"""print("onmove called")def quit():"""关闭事件处理"""print("quit called")def handle_event1():"""处理事件方案1"""# 事件列表events = ["click", "dbclick", "hover", "move", "quit"]while True:# 随机事件event = random.choice(events)print("event:", event)if event == "click":onclick()elif event == "dbclick":# ondbclick()passelif event == "hover":onhover()elif event == "move":onmove()elif event == "quit":quit()break# elif event == "..."print()
运行结果
event: move
onmove calledevent: hover
onhover calledevent: click
onclick calledevent: quit
quit called
方案二、函数引用
# 事件处理函数的引用对照字典
# 事件event为 key, 对应的事件处理函数引用为 value
event_dict = {"click": onclick,"hover": onhover,"move": onmove,"quit": quit
}def handle_event2():"""处理事件方案2"""# 事件列表events = ["click", "dbclick", "hover", "move", "quit"]while True:# 随机事件event = random.choice(events)# 获取事件处理函数event_func = event_dict.get(event, None)print("event:", event)# 判断是否从字典中获取到事件函数if event_func:event_func()print()if event == "quit":break
运行结果
event: hover
onhover calledevent: hover
onhover calledevent: hover
onhover calledevent: click
onclick calledevent: quit
quit called
使用函数引用,发现程序结构更简单明了,实现也非常巧妙。
Python 中闭包的使用
def func(number):# 在函数内部再定义一个函数,并且这个函数用到了外部函数的变量,# 那么将这个函数以及用到的一些变量称之为闭包def func_in(number_in):print("in func_in 函数, number_in is %d" % number_in)return number + number_in# 这里返回的就是闭包return func_in# 给func函数赋值,这个20就是给参数number
ret = func(20)# 注意这里的100其实给参数number_in
print(ret(100))#注 意这里的200其实给参数number_in
print(ret(200))
运行结果
in func_in 函数, number_in is 100
120
in func_in 函数, number_in is 200
220
闭包案例 - 直线方程配置
# -------------------- 直线方程配置 -------------------- #
def line_conf(a, b):def line(x):print("x =", x)return a*x + bprint("y = {}*x + {}".format(a, b))return line# y = 2*x + 1
line1 = line_conf(2, 1)
print("y =", line1(5), "\n")# y = 4*x + 5
line2 = line_conf(4, 5)
print("y =", line2(5), "\n")
运行结果
y = 2*x + 1
x = 5
y = 11 y = 4*x + 5
x = 5
y = 25
这个例子中,函数 line
与变量 a,b
构成闭包。在创建闭包的时候,我们通过 line_conf
的参数 a,b
说明了这两个变量的取值,这样,我们就确定了函数的最终形式 ( y = 2x + 1和 y = 4x + 5)。我们只需要变换参数 a,b
,就可以获得不同的直线表达式函数。由此,我们可以看到,闭包也具有提高代码可复用性的作用。
如果没有闭包,我们需要每次创建直线函数的时候同时说明 a, b, x
。这样,我们就需要更多的参数传递,也减少了代码的可移植性。
注意: 由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存
修改外部函数中的变量
In [23]: def counter(start=0):...: def incr():...: # nonlocal start...: start += 1...: return start...: return incr...:In [24]: c = counter(5)In [25]: c()
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
<ipython-input-25-cd4a6ef0eda0> in <module>
----> 1 c()<ipython-input-23-7cfd2d33ae43> in incr()2 def incr():3 # nonlocal start
----> 4 start += 15 return start6 return incrUnboundLocalError: local variable 'start' referenced before assignment
local variable 'start' referenced before assignment
变量没有被赋值直接引用了,可以发现在内部函数不可以直接使用外部函数变量。
Python3的方法 - nonlocal关键字
# -------------------- Python3修改外部函数中的变量 -------------------- #
def counter(start=0):def incr():nonlocal startstart += 1return startreturn incr# ipython 测验
In [12]: c1 = counter(5)In [13]: c1()
Out[13]: 6In [14]: c1()
Out[14]: 7In [15]: c2 = counter(50)In [16]: c2()
Out[16]: 51In [17]: c2()
Out[17]: 52In [18]: c1()
Out[18]: 8In [19]: c1()
Out[19]: 9In [20]: c2()
Out[20]: 53In [21]: c2()
Out[21]: 54
Python2的方法 - 列表
# -------------------- Python2修改外部函数中的变量 -------------------- #
def counter(start=0):count = [start]def incr():count[0] += 1return count[0]return incr# ipython 测验
In [31]: c1 = counter(5)In [32]: c1()
Out[32]: 6In [33]: c1()
Out[33]: 7In [34]: c2 = counter(100)In [35]: c2()
Out[35]: 101In [36]: c2()
Out[36]: 102
公众号
新建文件夹X
大自然用数百亿年创造出我们现实世界,而程序员用几百年创造出一个完全不同的虚拟世界。我们用键盘敲出一砖一瓦,用大脑构建一切。人们把1000视为权威,我们反其道行之,捍卫1024的地位。我们不是键盘侠,我们只是平凡世界中不凡的缔造者 。
深入浅出Python闭包相关推荐
- python闭包的作用
作者整理笔记,记录备查 文章目录 1.变量作用域 2.闭包的概念 3.闭包的作用 3.1 读取函数内部的变量 3.2 让函数内部的局部变量始终保持在内存中 4.注意事项 4.1 内存消耗 4.2 使用 ...
- Python 闭包 (closure)深入解析
1. 闭包介绍 闭包概念: 在一个内部函数中,对外部作用域的变量进行引用,并且一般外部函数的返回值为内部函数,那么内部函数就被认为是闭包. 闭包作用: 1.装饰器 2.面向对象 3.实现单利模式 闭包 ...
- 深入理解Python闭包概念
闭包并不只是一个Python中的概念,在函数式编程语言中应用较为广泛.理解python中的闭包一方面是能够正确的使用闭包,另一方面可以好好体会和思考闭包的设计思想. 1.概念介绍 首先看一下维基上对闭 ...
- Python闭包及其作用域
Python闭包及其作用域 关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记 如果在一个内部函数里,对一个外部作用域(但不是全局作用域 ...
- Python 闭包详解
在函数编程中经常用到闭包.闭包是什么,它是怎么产生的及用来解决什么问题呢.给出字面的定义先:闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)(想想Erlang的外层函数传入一个 ...
- Python闭包与延迟绑定
Python闭包 1.什么是闭包,闭包必须满足以下3个条件: 必须有一个内嵌函数 内嵌函数必须应用外部函数的变量 外部函数的返回值必须是内嵌函数 举个栗子 # 嵌套函数但不是闭包 def nested ...
- 深入浅出Javascript闭包
深入浅出Javascript闭包 一.引子 闭包(closure)是 JavaScript 语言的一个难点,面试时常被问及,也是它的特色,很多高级应用都要依靠闭包实现.本文尽可能用简单易懂的话,讲清楚 ...
- python闭包的延迟绑定_浅析Python的闭包和延迟绑定
def multipliers(): return [lambda x : i * x for i in range(4)] print [m(2) for m in multipliers()] 你 ...
- Python闭包与装饰器
Python闭包与装饰器 一.闭包 函数是一个对象,所以可以对象的形式作为某个函数的结果返回.函数执行完后内部变量将会被回收.在闭包中,由于内部函数存在对外部函数的变量的引用,所以即使外部 ...
- 回归素材(part10)--深入浅出python机器学习
学习笔记,仅供参考,有错必纠 文章目录 深入浅出python机器学习 线性回归 基本原理 使用 L 2 L_2 L<
最新文章
- 经典排序算法 - 鸽巢排序Pigeonhole sort
- 使用ubuntu的tasksel安装LAMP全家桶
- fastai学习——第二个问题
- 移除apt源_apt提示处理归档 (--unpack)时出错的解决办法
- Spring Boot(5)---第一个Spring Boot应用程序
- Java的八大常用类
- sql 根据省份证号码提取年龄
- python如何安装pdfminer_Python 3.6 中使用pdfminer解析pdf文件的实现
- 技术团队管理经验总结(持续更新)
- 「漫談數位音樂」5~音樂CD複製要點
- 新浪短网址php源码,新浪短网址api接口腾讯短网址api接口分享
- 本本CPU控制让游戏3D效果最佳境界
- docker镜像启动后端口号是多少_RSS、智能家居、个人博客、维基百科……Docker 入门指南...
- eclipse打不开的问题
- 社会保障计算机考试证书查询,在电脑上如何查询职业资格证书?
- 中职一年级计算机学情分析,学情分析
- HigherHRNet预训练模型——网盘下载
- 【GAMS与C++的交互】
- 每日区块链:智能合约是否是区块链的最佳创新?
- php代码审计【25】齐博CMS 无限制put 漏洞
热门文章
- jmeter录制脚本(代理)
- 网易云音乐缓存转换至mp3(Python实现)
- MUSIC算法相关原理知识(物理解读+数学推导+Matlab代码实现)
- 分辨率测试方法 ——TV line检测
- iso12233测试方法_ISO12233分辨率图像测试卡使用时拍摄方法
- 用友u8cloud使用教程_用友财务软件还不会操作?看完这些操作,工作得心应手...
- bzero和memset函数
- c语言编程编写笑脸,用C语言编写笑脸游戏.doc
- Physics Bodies(中文翻译)—UE4官方文档
- 第三方支付易宝支付的具体实现