闭包
参考: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())