如何理解及使用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
猜你喜欢
- 一个完整的程序离不开日志,无论是开发阶段,还是测试阶段,亦或程序运行阶段,都可以通过日志查看程序的运行情况,或是定位问题。下面是对 pyth
- 与没有数据库的网站相比,数据库的存取会降低你的系统性能。但是大多数情况下,网站和数据库有密不可分的关系,正是数据库给站点提供了大容量、多样性
- 分支结构的应用场景迄今为止,我们写的Python代码都是一条一条语句顺序执行,这种结构的代码我们称之为顺序结构。然而仅有顺序结构并不能解决所
- 读取csv文件时添加表头/列名有时,我们读取的csv文件数据时发现没有表头/列名,是因为Python读取csv文件数据本来就没有表头,用pa
- 目录一、for在 Python 中使用循环进行迭代二、使用 Python 的 enumerate()三、用 Python 练习 enumer
- 如下所示:class bcolors: HEADER = '\033[95m' OKBLUE = &
- python绘制横向水平柱状条形图Bar,供大家参考,具体内容如下import matplotlibimport randomimport
- 原理:print() 函数会把内容放到内存中, 内存中的内容并不一定能够及时刷新显示到屏幕中(应该是要满足某个条件,这个条件现在还不清楚)。
- pynput这个库让你可以控制和监控输入设备。对于每一种输入设备,它包含一个子包来控制和监控该种输入设备:pynput.mouse:包含控制
- 本文实例讲述了Python从序列中移除重复项且保持元素间顺序不变的方法。分享给大家供大家参考,具体如下:问题:从序列中移除重复的元素,但仍然
- python socket多线程实现客户端与服务器连接,供大家参考,具体内容如下之前因为一些作业需要完成一个服务器监听多个客户端的程序,于是
- 下面列出Python正则表达式的几种匹配用法:此外,关于正则的一切http://deerchao.net/tutorials/regex/r
- 谷歌在大型图像数据库ImageNet上训练好了一个Inception-v3模型,这个模型我们可以直接用来进来图像分类。下载链接: https
- 1.折线图 plt.plot()常用的一些参数:颜色(color):‘c’ 青红(cyan)&
- fso对象CreateTextFile方法调用时可能会报“无效的过程调用或参数”错误,在使用ASP生成静态页面时,如果传入的字符串参数编码为
- 之前想爬取一些淘宝的数据,后来发现需要登录,找了很多的资料,有个使用request的sessions加上cookie来登录的,cookie的
- javascript 常见汉字转换成拼音,上下行排列,方便对比,速度快,你可以把代码复制到本地,作为一个不错的汉字转换拼音的工具!转换效果图
- 最近一段时间一直在研究yolo物体检测,基于网络上很少有yolo的分类预训练和yolo9000的联合数据的训练方法,经过本人的真实实验,对这
- 1. RS.OPEN SQL,CONN,A,B,C2. CONN.EXECUTE(SQL,RowsAffected,C)参数含义:SQL的值
- 导语害!现在是10月份了,国庆过完也降温了——还有几个月就过年了,哦吼~这一年就快过去了,不知道小编带给大家这么多的表白代码都用了没?用了没