如何理解及使用Python闭包
作者:Warmer_Sweeter 发布时间:2021-12-22 23:50:59
目录
一、Python 中的作用域规则和嵌套函数
二、定义闭包函数
三、何时使用闭包?
四、总结
一、Python 中的作用域规则和嵌套函数
每当执行一个函数时,就会创建一个新的局部命名空间,它表示包含函数体内分配的函数参数和变量名的局部环境。我们可以将名称空间看作一个字典,其中键是对象名称,值是对象本身。
解析名称时,解释器首先搜索本地命名空间。如果不存在匹配,则搜索全局名称空间,该名称空间是定义函数的模块。如果仍然没有找到匹配项,则在引发 NameError 异常之前最终检查内置名称空间。下图说明了这一点:
让我们考虑下面的例子:
age = 27
def birthday():
age = 28
birthday()
print(age) # age will still be 27
>>
27
当变量在函数内部赋值时,它们总是绑定到函数的本地名称空间; 因此,函数体中的变量 age 指的是一个包含值28的全新对象,而不是外部变量。可以使用全局语句更改此行为。下面的示例强调了这一点:
age = 27
name = "Sarah"
def birthday():
global age # 'age' is in global namespace
age = 28
name = "Roark"
birthday() # age is now 28. name will still be "Sarah"
Python 也支持嵌套函数定义(函数内部的函数):
def countdown(start):
# This is the outer enclosing function
def display():
# This is the nested function
n = start
while n > 0:
n-=1
print('T-minus %d' % n)
display()
# We execute the function
countdown(3)
>>>
T-minus 3
T-minus 2
T-minus 1
二、定义闭包函数
在上面的示例中,如果函数 countdown()的最后一行返回了 display 函数而不是调用它,会发生什么情况?这意味着该函数的定义如下:
def countdown(start):
# This is the outer enclosing function
def display():
# This is the nested function
n = start
while n > 0:
n-=1
print('T-minus %d' % n)
return display
# Now let's try calling this function.
counter1 = countdown(2)
counter1()
>>>
T-minus 2
T-minus 1
使用值2调用 countdown()函数,并将返回的函数绑定到名称 counter1。在执行 counter1()时,它使用最初提供给 countdown ()的 start 值。因此,在调用 counter1()时,尽管我们已经执行了 count1()函数,但仍然记住这个值。
这种将一些数据(本例中为2)附加到代码的技术在 Python 中称为闭包。
即使变量超出范围或函数本身从当前名称空间中移除,也会记住封闭范围中的这个值。我们可以尝试下面的代码来确认:
>>> del countdown
>>> counter1()
T-minus 2
T-minus 1
>>> countdown(2)
Traceback (most recent call last):
...
NameError: name 'countdown' is not defined
三、何时使用闭包?
当一个类中实现的方法很少(大多数情况下只有一个方法)时,闭包可以提供一个替代的、更优雅的解决方案。此外,如果我们希望根据延迟或延迟计算的概念编写代码,闭包和嵌套函数特别有用。下面是一个例子:
from urllib.request import urlopen
def page(url):
def get():
return urlopen(url).read()
return get
在上面的示例中,page ()函数实际上并不执行任何计算。相反,它只是创建并返回一个函数 get () ,该函数在调用 web 页面时获取页面内容。因此,在 get ()中执行的计算实际上被延迟到计算 get ()时程序中的某个后续点。例如:
>>> url1 = page("http://www.google.com")
>>> url2 = page("http://www.bing.com")
>>> url1
<function page.<locals>.get at 0x10a6054d0>
>>> url2
<function page.<locals>.get at 0x10a6055f0>
>>> gdata = url1() # Fetches http://www.google.com
>>> bdata = url2() # Fetches http://www.bing.com
>>>
可以找到闭包函数中包含的值。
所有函数对象都有一个 _closure_ 属性,如果它是一个闭包函数,那么这个属性将返回一组单元格对象。根据上面的例子,我们知道 url1和 url2是闭包函数。
>>> page.__closure__ # Returns None since not a closure
>>> url1.__closure__
(<cell at 0x10a5f1250: str object at 0x10a5f3120>,)
单元格对象具有存储关闭值的属性 cell_contents。
>>> url1.__closure__[0].cell_contents
'http://www.google.com'
>>> url2.__closure__[0].cell_contents
'http://www.bing.com'
四、总结
当嵌套函数引用其封闭范围中的值时,可以定义 Python 中的闭包。闭包提供了某种形式的数据隐藏。闭包还可以是一种高效的方法,可以在一系列函数调用之间保持状态。用 Python 创建一个闭包函数:
我们必须有一个嵌套的函数
嵌套函数必须引用封闭函数中定义的值
封闭函数必须返回嵌套函数
来源:https://blog.csdn.net/weixin_38739735/article/details/117393726


猜你喜欢
- 我们在建立一个大型网站的时候会有很多副页面框架模式,甚至一些细节元素都是相同的。但令人困扰的是更新它们却要费些周折,要一遍遍地反复更新每个页
- 当然如果想了解更多编辑器的原理制作方法,只有你自己去下载一个在线编辑器,慢慢研究,相信会有更多的收获!HTML在线编辑器的基本概念1,什么是
- 在python显示图象时,我们用matplotlib模块时会遇到图像色彩失真问题,究竟是什么原因呢,下面就来看看究竟。待显示图像为:impo
- 在平时开发过程中,经常遇到需要在数据中获取特定的元素的信息,如到达目的地最近的车站,橱窗里面最贵的物品等等。怎么办?看下面方法一: 利用数组
- 本文介绍MySQL与Redis缓存的同步的两种方案方案1:通过MySQL自动同步刷新Redis,MySQL触发器+UDF函数实现方案2:解析
- 一、连接MYSQL格式: mysql -h主机地址 -u用户名 -p用户密码1、 连接到本机上的MYSQL。首先打开DOS窗口,然后进入目录
- 无论哪种编程语言,时间肯定都是非常重要的部分,今天来看一下python如何来处理时间和python定时任务,注意咯:本篇所讲是python3
- 一、下载anaconda第一步当然是下载anaconda了,官方网站的下载需要用迅雷才能快点,或者直接到清华大学镜像站下载。当然这里推荐脚本
- 目录通过python的tkinter实现简单的注册登录代码截图登录页面注册页面个人主页修改个人信息失败修改个人信息成功重新登录twb总结通过
- 刚才显示数据的时候遇到一个日期里面带T的问题,就是天数跟小时数之间出现了一个T。 表字段里面也没有这个T,后来查询度娘,是因为json处理的
- 分形几何学的基本思想:客观事物具有自相似性的层次结构,局部和整体在形态,功能,信息,时间,空间等方面具有统计意义上的相似性,称为自相似性,自
- 以下保存成 App.xml , 与asp文件放在相同目录下! 代码如下: <?xml version="1.0"
- 一、安装xlrd地址下载后,使用 pip install .whl 安装即好。查看帮助:>>> import xlrd&g
- print() 函数使用以 % 开头的转换说明符对各种类型的数据进行格式化输出。转换说明符(Conversion Specifier)只是一
- 一、修改表格数据类型 DataFrame 列的顺序实战场景:Pandas 如何修改表格数据类型 DataFrame 列的顺序1.1
- 这篇文章主要介绍了django自定义模板标签过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友
- 本文实例讲述了Python设计模式之简单工厂模式。分享给大家供大家参考,具体如下:简单工厂模式(Simple Factory Pattern
- SQL Server中新增加了XML.Modify()方法,分别为xml.modify(insert),xml.modify(delete)
- 当你连接到MySQL服务器时,你应使用一个密码。密码不以明文在上传输。客户端连接序列中的密码处理在MySQL 4.1.1中已经升级,很安全。
- 使用Python可视化Pygal包来生成可缩放的矢量图形文件!对于在尺寸不同的屏幕上显示图标,它们将自动缩放以适合观看者的屏幕,如果以在线的