对python中闭包概念的理解

首先通过一例子直观理解一下闭包是什么

实现一个函数avg(),每次调用该函数,传入一个数值,返回历史调用中,所有入参的平均值。
>>> avg(1)
1.0
>>> avg(2)
1.5
>>> avg(3)
2.0

方式一:

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 = Agerager()
avg(1)
avg(2)
avg(3)

这种方式是传统的面向对象的实现方式,python还提供一种闭包的机制可以实现上述功能。
方式二:

def make_averager():
    series = []
    def averager(new_value):
        series.append(new_value)
        total = sum(series)
        return total / len(series)
    return averager

avg = make_averager()
avg(1)
avg(2)
avg(3)

第二种方式,是定义了一个高阶函数,所谓高阶函数就是入参或者返回值为函数的函数。make_averager()的返回值是一个函数,并且该函数是在自己的函数体内定义的。而且还有一点需要注意,就是内部函数averager()中使用了外部函数的局部变量series。被当做返回值的averager就是所谓的闭包。
综上,闭包出现的条件如下:

  • 出现函数的嵌套定义。
  • 嵌套函数引用了外层函数第一的变量。
  • 外层函数返回嵌套函数。

有一点需要注意,为什么make_averager()已经执行完返回了,但averager还能使用make_averager中定义的局部变量呢?
在python中有一个重要的思想:函数是第一对象。所以函数可以像一般的对象一样,可以含有属性。闭包作为一种函数对象,就拥有自己的属性。avg的属性closure中保存着avg可以使用的外层函数的局部变量。这些变量有一个学术上的名字叫自由变量
可以通过如下方式查看自由变量的值:

>>> avg.__closure__[0].cell_contents
[1, 2, 3]

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容