python 闭包
首先提一下外函数和内函数:如果在一个函数的内部定义了另一个函数,外部的我们叫它外函数,内部的我们就叫它内函数。
示例一:
#函数的局部作用域导致出错
def outer_fun(): def inner_fun(): print('Nice to meet you!') inner_fun()
------------------------ NameError: name 'inner_fun' is not defined
示例二:
#通过外函数返回内函数的引用来执行内函数
def outer_fun(): def inner_fun(): print('Nice to meet you!') return inner_fun outer_fun()() # 或者 # fun = outer_fun() # fun() ---------------------- Nice to meet you!
闭包:
在一个外函数中定义了一个内函数,内函数里运用了外函数定义的局部变量(这时这个外函数的局部变量就成了内函数的环境变量),并且外函数的返回值是内函数的引用(这个引用的对象中包含了函数的代码和它的环境变量),这样就构成了一个闭包。即闭包 = 内部函数 + 环境变量。
我们知道,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但对闭包而言,如果外函数在结束的时候发现有自己的局部变量将来会在内部函数中用到,就先把这个局部变量绑定给内部函数,再结束自己。
示例三:
#此时闭包的环境变量a是全局变量中定义的a = 1
def outer_fun(): def inner_fun(): print(a) return inner_fun a = 1 outer_fun()() -------------------- 1
示例四:
#此时闭包中的环境变量a是外部函数中定义的a = 0
def outer_fun(): a = 0 def inner_fun(): print(a) return inner_fun a = 1 outer_fun()() -------------------- 0
从中也可以发现,当形成闭包之后闭包内函数的执行将不受闭包之外变量的影响。
如果内部函数想要改变它的环境变量(外部函数定义的局部变量),需要使用nonlocal先声明该变量。看下面这个例子:
示例五:
def outer_fun(a): def inner_fun(): nonlocal a a += 1 print(a) return inner_fun a = outer_fun(0) a() a() --------------- 1 2
无环境不闭包,例如下面这个没有形成闭包的示例(属性__closure__包含函数所需的环境变量):
示例六:
#变量a并不是内部函数的环境变量,而是在内部函数中定义的局部变量
def outer_fun(): a = 0 def inner_fun(): a = 1 return inner_fun f = outer_fun() print(f.__closure__) -------------- None
示例七:
def outer_fun(): a = 0 def inner_fun(): print(a) return inner_fun f = outer_fun() print(f.__closure__) --------------------- (<cell at 0x00000168C565EC48: int object at 0x00007FFB889CEEE0>,)
总结
闭包所形成的特点就是,外函数将内函数以及它的环境变量一起打包,最后作为返回之前返回出去。并且在同一个外函数的环境下多次调用内函数时,如果内函数改变了环境变量,那么该改变将保存,例如示例五。
蒹葭苍苍,白露为霜;
所谓伊人,在水一方。