说说 Python 中的闭包

  • 时间:2021-03-20 18:05 作者:deniro 来源: 阅读:447
  • 扫一扫,手机访问
摘要:闭包不好了解,所以先从示例说起。假设我们需要计算平均值,这些值会从外层传递进来,而后被保存在内部。(1) 非闭包方式实现class Averager(): def __init__(self): self.series = [] def __call__(self, new

闭包不好了解,所以先从示例说起。

假设我们需要计算平均值,这些值会从外层传递进来,而后被保存在内部。

(1) 非闭包方式实现

class Averager():    def __init__(self):        self.series = []    def __call__(self, new_value):        self.series.append(new_value)        total = sum(self.series)        return total / len(self.series)avg = Averager()logging.info('avg(10) -> %s', avg(10))logging.info('avg(20) -> %s', avg(20))logging.info('avg(30) -> %s', avg(30))

运行结果:


  1. 非闭包方式定义了一个类,名为 Averager。而后在初始化方法中为该类定义了一个数组 series,用于保存传入进来的数值。
  2. 接着使用 __call__ 使得该类实例对象可以像调用普通函数那样,以“对象名()”的形式被使用1。它接收一个参数作为需要计算的新数值,内部被保存在 series 数组中。

(2) 闭包方式实现

这个平均数计算方式可以采用函数式编程方式来实现。

def make_averager():    series = []    def averager(new_value):        series.append(new_value)        total = sum(series)        return total / len(series)    return averageravg = make_averager()logging.info('avg(10) -> %s', avg(10))logging.info('avg(20) -> %s', avg(20))logging.info('avg(30) -> %s', avg(30))

运行结果与上例相同。

  1. 我们定义了一个 make_averager 函数,其内部又定义了一个名为 averager(new_value) 的函数,里面是计算平均数的算法;
  2. 传入的参数被保存在外层的 series 数组中;
  3. 最后返回这个内部函数。

黄色区域表示产生闭包现象的代码段。其中的 series 数组是自由变量(free variable),不受内部函数 averager 的影响,所以可以保存所有传入的变量值。

内部函数 averager 的局部作用域内的变量,都会在函数被调用后失效。

通过 __code__ 属性可以看到 avg 函数中的变量名称。__code__ 属性是编译后的函数定义体。

logging.info('avg.__code__.co_varnames -> %s', avg.__code__.co_varnames)logging.info('avg.__code__.co_freevars -> %s', avg.__code__.co_freevars)

运行结果:


其中 co_varnames 表示局部变量;co_freevars 表示自由变量。这与我们之前所形容的闭包场景一致。

闭包中的自由变量值保存在 avg 函数的 __closure__ 属性中。它是一组 cell 对象列表,每个 cell 对象与 co_freevars 列表中的名称逐个对应:

INFO - avg.__closure__ -> (<cell at 0x000002A8AF736D38: list object at 0x000002A8AF9C7DC8>,)INFO - avg.__closure__[0].cell_contents -> [10, 20, 30]

运行结果:


closure 翻译过来就是闭包。


通过闭包,我们可以保留住定义的自由变量的值。这样函数调用后,我们依然可以使用这些变量。


  1. Python __call__()方法(详解版).
  2. Luciano Ramalho (作者),安道,吴珂 (译者).流畅的Python[M].人民邮电出版社,2017:312-315.
  • 全部评论(0)
最新发布的资讯信息
【系统环境|】从谷歌到手机厂商都下决心了,要清除32位应用这匹“害群之马”(2025-10-17 05:41)
【系统环境|】Windows上使用QEMU创建aarch64(ARM64)虚拟机(2025-10-17 05:40)
【系统环境|】nodejs 如何安装在aarch64平台(2025-10-17 05:39)
【系统环境|】常用git命令-从远程更新代码合并分支、提交代码等(2025-10-17 05:38)
【系统环境|】技术干货|常用的 Git 功能和选项(2025-10-17 05:38)
【系统环境|】掌握git命令,图解一目了然(2025-10-17 05:37)
【系统环境|】总结几个常用的Git命令的使用方法(2025-10-17 05:36)
【系统环境|】这篇 Git 教程太清晰了,很多 3 年经验程序员都收藏了(2025-10-17 05:35)
【系统环境|】Git常用命令及操作指南(2025-10-17 05:35)
【系统环境|】「实用」盘点那些开发中最常用的Git命令(2025-10-17 05:34)
手机二维码手机访问领取大礼包
返回顶部