闭包简述

闭包概念:在一个内部函数中,对外部作用域的变量进行引用, (并且一般外部函数的返回值为内部函数),那么内部函数就被认为是闭包 (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闭包相关推荐

  1. python闭包的作用

    作者整理笔记,记录备查 文章目录 1.变量作用域 2.闭包的概念 3.闭包的作用 3.1 读取函数内部的变量 3.2 让函数内部的局部变量始终保持在内存中 4.注意事项 4.1 内存消耗 4.2 使用 ...

  2. Python 闭包 (closure)深入解析

    1. 闭包介绍 闭包概念: 在一个内部函数中,对外部作用域的变量进行引用,并且一般外部函数的返回值为内部函数,那么内部函数就被认为是闭包. 闭包作用: 1.装饰器 2.面向对象 3.实现单利模式 闭包 ...

  3. 深入理解Python闭包概念

    闭包并不只是一个Python中的概念,在函数式编程语言中应用较为广泛.理解python中的闭包一方面是能够正确的使用闭包,另一方面可以好好体会和思考闭包的设计思想. 1.概念介绍 首先看一下维基上对闭 ...

  4. Python闭包及其作用域

    Python闭包及其作用域 关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记 如果在一个内部函数里,对一个外部作用域(但不是全局作用域 ...

  5. Python 闭包详解

    在函数编程中经常用到闭包.闭包是什么,它是怎么产生的及用来解决什么问题呢.给出字面的定义先:闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)(想想Erlang的外层函数传入一个 ...

  6. Python闭包与延迟绑定

    Python闭包 1.什么是闭包,闭包必须满足以下3个条件: 必须有一个内嵌函数 内嵌函数必须应用外部函数的变量 外部函数的返回值必须是内嵌函数 举个栗子 # 嵌套函数但不是闭包 def nested ...

  7. 深入浅出Javascript闭包

    深入浅出Javascript闭包 一.引子 闭包(closure)是 JavaScript 语言的一个难点,面试时常被问及,也是它的特色,很多高级应用都要依靠闭包实现.本文尽可能用简单易懂的话,讲清楚 ...

  8. python闭包的延迟绑定_浅析Python的闭包和延迟绑定

    def multipliers(): return [lambda x : i * x for i in range(4)] print [m(2) for m in multipliers()] 你 ...

  9. Python闭包与装饰器

    Python闭包与装饰器 一.闭包       函数是一个对象,所以可以对象的形式作为某个函数的结果返回.函数执行完后内部变量将会被回收.在闭包中,由于内部函数存在对外部函数的变量的引用,所以即使外部 ...

  10. 回归素材(part10)--深入浅出python机器学习

    学习笔记,仅供参考,有错必纠 文章目录 深入浅出python机器学习 线性回归 基本原理 使用 L 2 L_2 L<

最新文章

  1. 经典排序算法 - 鸽巢排序Pigeonhole sort
  2. 使用ubuntu的tasksel安装LAMP全家桶
  3. fastai学习——第二个问题
  4. 移除apt源_apt提示处理归档 (--unpack)时出错的解决办法
  5. Spring Boot(5)---第一个Spring Boot应用程序
  6. Java的八大常用类
  7. sql 根据省份证号码提取年龄
  8. python如何安装pdfminer_Python 3.6 中使用pdfminer解析pdf文件的实现
  9. 技术团队管理经验总结(持续更新)
  10. 「漫談數位音樂」5~音樂CD複製要點
  11. 新浪短网址php源码,新浪短网址api接口腾讯短网址api接口分享
  12. 本本CPU控制让游戏3D效果最佳境界
  13. docker镜像启动后端口号是多少_RSS、智能家居、个人博客、维基百科……Docker 入门指南...
  14. eclipse打不开的问题
  15. 社会保障计算机考试证书查询,在电脑上如何查询职业资格证书?
  16. 中职一年级计算机学情分析,学情分析
  17. HigherHRNet预训练模型——网盘下载
  18. 【GAMS与C++的交互】
  19. 每日区块链:智能合约是否是区块链的最佳创新?
  20. php代码审计【25】齐博CMS 无限制put 漏洞

热门文章

  1. jmeter录制脚本(代理)
  2. 网易云音乐缓存转换至mp3(Python实现)
  3. MUSIC算法相关原理知识(物理解读+数学推导+Matlab代码实现)
  4. 分辨率测试方法 ——TV line检测
  5. iso12233测试方法_ISO12233分辨率图像测试卡使用时拍摄方法
  6. 用友u8cloud使用教程_用友财务软件还不会操作?看完这些操作,工作得心应手...
  7. bzero和memset函数
  8. c语言编程编写笑脸,用C语言编写笑脸游戏.doc
  9. Physics Bodies(中文翻译)—UE4官方文档
  10. 第三方支付易宝支付的具体实现