如何理解及使用Python闭包

 更新时间:2021年06月01日 10:14:56   作者:Warmer_Sweeter  
闭包是优雅的 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 创建一个闭包函数:

  • 我们必须有一个嵌套的函数
  • 嵌套函数必须引用封闭函数中定义的值
  • 封闭函数必须返回嵌套函数

到此这篇关于如何理解及使用Python闭包的文章就介绍到这了,更多相关Python闭包内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 在python中利用GDAL对tif文件进行读写的方法

    在python中利用GDAL对tif文件进行读写的方法

    今天小编就为大家分享一篇在python中利用GDAL对tif文件进行读写的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-11-11
  • Django框架基础认证模块auth应用示例

    Django框架基础认证模块auth应用示例

    这篇文章主要为大家介绍了Django框架认证模块auth示例应用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03
  • pycham查看程序执行的时间方法

    pycham查看程序执行的时间方法

    今天小编就为大家分享一篇pycham查看程序执行的时间方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-11-11
  • Python-Tkinter Text输入内容在界面显示的实例

    Python-Tkinter Text输入内容在界面显示的实例

    今天小编就为大家分享一篇Python-Tkinter Text输入内容在界面显示的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-07-07
  • Python模块对Redis数据库的连接与使用讲解

    Python模块对Redis数据库的连接与使用讲解

    这篇文章主要介绍了Python模块对Redis数据库的连接与使用,通过实例代码给大家介绍了Python连接Redis数据库方法,Python使用连接池连接Redis数据库方法,感兴趣的朋友跟随小编一起看看吧
    2021-07-07
  • keras.layer.input()用法说明

    keras.layer.input()用法说明

    这篇文章主要介绍了keras.layer.input()用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-06-06
  • PyTorch中的torch.cat简单介绍

    PyTorch中的torch.cat简单介绍

    这篇文章主要介绍了PyTorch中的torch.cat,包torch包含了多维疑是的数据结构及基于其上的多种数学操作,包含了多维张量的数据结构以及基于其上的多种数学运算,更多相关资料 需要的小伙伴可以参考一下
    2022-03-03
  • kNN算法python实现和简单数字识别的方法

    kNN算法python实现和简单数字识别的方法

    这篇文章主要介绍了kNN算法python实现和简单数字识别的方法,详细讲述了kNN算法的优缺点及原理,并给出了应用实例,需要的朋友可以参考下
    2014-11-11
  • Python HMAC模块维护数据安全技术实例探索

    Python HMAC模块维护数据安全技术实例探索

    本篇博客将带领读者深入探索Python中HMAC模块的高级应用,通过丰富的示例代码和详细的解释,揭示HMAC在实际应用场景中的多面光芒,从基础概念到密码存储、文件完整性验证、API安全,再到与加密算法的巧妙结合
    2024-01-01
  • Python搭建自己IP代理池的方法实现

    Python搭建自己IP代理池的方法实现

    本文主要介绍了Python搭建自己IP代理池的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02

最新评论