美文网首页程序员
说说 Python 中的闭包

说说 Python 中的闭包

作者: deniro | 来源:发表于2021-02-10 17:36 被阅读0次

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

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

(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 averager


avg = 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.

相关文章

  • python函数之闭包

    目录 python函数之闭包什么是闭包python中的namespace闭包的条件闭包的优点 python函数之闭...

  • 说说Python中的闭包

    原文出处: cicaday Python中的闭包不是一个一说就能明白的概念,但是随着你往学习的深入,无论如何你都需...

  • 说说 Python 中的闭包

    闭包不好理解,所以先从示例说起。 假设我们需要计算平均值,这些值会从外层传递进来,然后被保存在内部。 (1) 非闭...

  • python闭包学习

    参考文章 python闭包python闭包一步一步教你认识Python闭包深入浅出python闭包

  • Python 中的闭包

    Python 中的闭包:+ http://python.jobbole.com/82296/

  • Python闭包与ObjC的block的区别与联系

    首先明确一下Python闭包和ObjC中block的定义在python中闭包是这么定义的——内层函数引用了外层函数...

  • Python 闭包使用注意点

    1 Python 闭包 今天,聊下 python 的闭包。在函数编程中经常用到闭包。 闭包是什么,它是怎么产生的及...

  • 彻底理解JS闭包

    闭包并不是JS所独有的,在计算机科学中其是一个普遍的概念,在Python中也有闭包的概念,但闭包在Python应用...

  • Python装饰器(Decorator)完全指南-基础篇

    Decorator基本指南 前提知识 Python中的闭包(closure) 所谓闭包,指的是附带数据的函数对象。...

  • python之理解闭包和装饰器

    python之理解闭包和装饰器 1、闭包函数 1.1 python中函数都是对象 结果: 上面定义一个shut函数...

网友评论

    本文标题:说说 Python 中的闭包

    本文链接:https://www.haomeiwen.com/subject/zkjkxltx.html