简介

闭包(closure)是函数式编程的重要的语法结构,Python 也支持这一特性,下面就开始介绍 Python 中的闭包。

ps. 函数式编程是一种编程方式。我们熟知的面向对象编程及面向过程编程都是一种编程方式。这些都对代码进行提炼抽象概括,使得代码重用性可用性更高。

 

闭包通俗的来讲就是:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。

 

举个例子:

def FunX(x):
    def FunY(y):           #内部函数FunY就是一个闭包
        return x * y
    return FunY             #Python里面基本所有的东西都是对象,所以可以直接把函数对象返回

 

闭包的调用

对于上述的例子有

>>>i = FunX(8)
>>>i
<function FunX.<locals>.FunY at 0x0000000002E931E0>

>>>type(i)
<class 'function'>

>>>i(5)
40

 

>>>FunX(8)(5)
40

注意事项

 

由于闭包的概念是由内部函数演变而来,所以不能在外部函数的外边对内部函数进行调用

如果对上述例子的 FunY() 直接调用的话,如 FunY(5) 会出现 NameError: name 'FunY' is not defined 的错误

 

在闭包中,外部函数的局部变量对内部函数的局部变量相当于全局变量之于局部变量的关系。

在内部函数中只能对外部函数的局部变量进行访问但不能修改,例子如下:

>>>def Fun1():
       x = 5
       def Fun2():
           x *= x
           return x
       return Fun2()      #这里return Fun2 和 return Fun2() 有什么区别没太明白。但是如果写的是Fun2,则下述代码不会报错

>>>Fun1()

会报错 UnboundLocalError: local variable 'x' referenced before assignment

 

要想达到修改 x 的目的,在 Python3 之前没有直接的方法,只能通过容器类型(元组,列表,字符串都是)间接达到:

>>>def Fun1():
       x = [5]
       def Fun2():
           x[0] *= x[0]
           return Fun2()
       return x[0]

而在 Python3 中可直接通过关键字 nonlocal 实现

>>>def Fun1():
       x = [5]
       def Fun2():
           nonlocal x             #强制将x声明为不是一个局部变量
           x[0] *= x[0]
           return Fun2()
       return x[0]