闭包

参考:https://www.cnblogs.com/Lin-Yi/p/7305364.html

参考:https://www.cnblogs.com/JohnABC/p/4076855.html

一、定义

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

闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)(想想Erlang的外层函数传入一个参数a, 内层函数依旧传入一个参数b, 内层函数使用a和b, 最后返回内层函数)。

这个从字面上很难理解,结合例子来看。

def addx(x):  
    def adder(y): return x + y  
    return adder  

在这段程序中,函数adder(y)是函数addx(x)的内嵌函数,并且是addx(x)函数的返回值。我们注意到一个问题:内嵌函数adder(y)中 引用到外层函数中的局部变量x。

如果在一个内部函数里:adder(y)就是这个内部函数,
对在外部作用域(但不是在全局作用域)的变量进行引用:x就是被引用的变量,x在外部作用域addx里面,但不在全局作用域里,
则这个内部函数adder就是一个闭包。

二、注意事项

2.1 闭包中是不能修改外部作用域的局部变量的

def fout():
    m = 0
    def finn():
        m = 1
        print(m)
    print(m)
    finn()
    print(m)        # 未改变m的值

fout()

2.2  未定义便引用

def fout():
    a = 1

    def finn():
        a = a + 1      # 出错
        return a
    return finn


t = fout()
print(t())

 这是因为在执行代码 c = fout()时,python会导入全部的闭包函数体finn()来分析其的局部变量,python规则指定所有在赋值语句左面的变量都是局部变量,则在闭包finn()中,变量a在赋值符号"="的左面,被python认为是finn()中的局部变量。再接下来执行print t()时,程序运行至a = a + 1时,因为先前已经把a归为finn()中的局部变量,所以python会在finn()中去找在赋值语句右面的a的值,结果找不到,就会报错。

解决的方法一:将a定义为可变数据类型。

def fout():
    a = [1]

    def finn():
        a[0] = a[0] + 1      # 未出错
        return a[0]
    return finn


t = fout()
print(t())

解决方法二:对a进行变量声明

def fout():
    a = 1

    def finn():
        nonlocal a
        a += 1
        return a
    return finn


t = fout()
print(t())
原文地址:https://www.cnblogs.com/qianslup/p/12188637.html