闭包函数

闭包是一种组织代码的结构,提高了代码的可重复实用性。

闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。

闭包和自由变量

Python中闭包从表现形式看,如果在一个内部函数中存在对外部函数作用域(不是全局作用域)的变量引用,那么内部函数就被认为是闭包(closure)函数,且外部返回值为内部函数。如

def line_conf(x):                    #x也是自由变量

a=1                        #自由变量

def line(b):

print(a*b+x)

return line

定义在外部函数内的但由内部函数引用或者使用的变量(外部函数的参数和局部变量)被称为自由变量。它是未绑定到特定对象的变量,这些变量不是在这个内部函数代码块内定义的,而是在定义这个代码块的环境中定义。所以可以说闭包是要执行的代码块和为自由变量提供引用的计算环境的结合。

闭包函数引用的外部变量不一定是其父函数的参数,也可以是父函数作用域内的任意变量。

闭包的作用

函数的局部变量仅在函数的执行期间可用,但闭包可以使得局部变量在函数外被访问成为可能。这样可以避免使用全局变量。如上述代码中,局部变量x、a在函数line_conf调用之后,能继续被ln函数引用。

>>> ln=line_conf(12)

>>> ln(2)

14

>>>

这是因为所有函数都有一个 __closure__属性,如果这个函数是一个闭包的话,那么它返回的是一个由 cell 对象组成的元组对象。cell 对象的cell_contents 属性就是闭包中的自由变量。

>>> ln.__closure__

(, )

>>>

>>> ln.__closure__[0].cell_contents

1

>>>

>>> ln.__closure__[1].cell_contents

12

>>>

这解释了为什么局部变量脱离函数之后,还可以在函数之外被访问的原因的,因为它存储在了闭包的 cell_contents中了。

在闭包函数中若有类似a = a + 1的代码,a会被python解释器认为是line函数的局部变量,从而引起“referenced before assignment”的错误。将a声明为nonlocal变量(仅在Python3支持),这样声明过后,就不会被认为是line函数的局部变量,而是会到上一层函数环境中寻找这个变量。

闭包函数还可以起到保存函数上一次运行状态的功能,如

def remainstate(x):

s=0

    def line():

        nonlocal s

        s=s+x

        print(s)

    return line

ln = remainstate(12)

ln()              #12

ln()     #24

ln()   #36

你可能感兴趣的:(闭包函数)