学科分类
目录
基础

闭包

我们都知道,Python函数是支持嵌套的。如果在一个内部函数中对外部函数作用域(非全局作用域)的变量进行引用,那么内部函数就会被称为闭包。闭包需要满足如下三个条件:

(1)存在于嵌套关系的函数中。

(2)嵌套的内部函数引用了外部函数的变量。

(3)嵌套的外部函数会将内部函数名作为返回值返回。

为了让读者更好地认识闭包,接下来,通过一个案例对闭包进行讲解,具体代码如下:

# 外部函数
  def outer(start=0):
        count = [start] # 函数内的变量
        # 内部函数
        def inner():
            count[0] += 1 # 引用外部函数的变量
            return count[0]
        # 返回内部函数的名称
        return inner
quote = outer(5)
print(quote())

在以上代码中,定义了一个嵌套函数。其中,outer函数是外部函数,inner是内部函数。

在outer函数中,首先定义了一个表示列表的变量count(该列表只有一个元素),然后定义了一个inner函数,最后将inner函数的名称返回。

在inner函数中,引用了外部函数定义的列表count,并对count的元素进行修改,修改后的列表元素使用return返回。

将调用外部函数outer的结果赋值给变量quote,quote引用的是inner函数占用的内存空间。

当调用了quote函数,实际上就是inner函数。

程序的运行结果如图1所示。

img

图1 运行结果

下面通过一张图来分析程序执行的过程,如图2所示。

image-20200616144457372

图2 程序执行的过程图

图2描述的具体过程如下:

(1)调用outer函数,并且把5传递给start参数。此时,start的值为5。

(2)由于start引用的值为5,所以count列表中存放的元素为5。

(3)返回内部函数的名称inner。

(4)将调用outer函数返回的inner赋值给quote变量,即quote=inner。此时,quote变量引用的是inner函数占用的内存空间。

(5)调用quote引用的函数,实质上相当于调用inner函数。此时,程序会来到inner函数的定义部分。

(6)让count列表的元素加1,即5+1=6。计算完以后,把得出的结果再次赋值为列表的元素。此时,列表中存放的元素为6。

(7)返回count列表的元素值6。

从变量的生命周期的角度来讲,在outer函数执行结束以后,变量count已经被销毁了。当outer函数执行完后,会再执行内部的inner函数,由于inner函数中使用了count变量,所以程序应该出现运行时错误。然而,程序仍能正常运行,这是为什么呢?究其原因,主要在于函数的闭包会记得外层函数的作用域,在inner函数(闭包)中引用了外部函数的count变量,所以程序是不会释放这个变量的。

点击此处
隐藏目录