1. 什么是闭包?
闭包应该说是一种写法,就是在函数嵌套的基础上,延伸了变量的作用域的写法。说起来可能有点绕,但是实际使用就不饶。
2. 我们考虑一下,为什么要用闭包,闭包到底是为了实现什么功能?
闭包其实是为了让函数本身保存当前的工作状态。就像类一样,类变量可以随着类里函数执行后,被改变:
比如:
class A:
def __init__():
self.cnt = 0
def add(self):
self.cnt = self.cnt+1
a = A()
a.add()
执行之后,我们就发现类变量self.cnt保存了运行的状态,也就是我们cnt+1可以被保存下来,并且不断叠加。
闭包的功能并不是必须的,因为完全可以用别的手段实现闭包。但是闭包的好处就在于,可以将保存状态本身这个工作,也放在函数里。
def func():
cnt = []
def add():
cnt.append(1)
return cnt
return add
然后我们创建一个函数func的对象
a = func() #会返回一个add函数对象
cnt = a() # [1]
cnt = a() # [1,1]
cnt = a() # [1,1,1]
但是cnt必须是可变的!!比如list这种,如果是不可变的,比如int,然后使用a = a+1在重新绑定的时候会出错!必须指明这个变量不是本地变量,而是访问的外部变量,用nonlocal关键字(和global类似)
def outer():
a = 0
def inner():
nonlocal a
a=a+1
return a
return inner
总的来说,如果要保存一个函数操作的历史记录,那么就可以使用闭包的写法,这样可以把一个变量一直存下来,供嵌套函数使用。如果不愿意写闭包,其实用类完全可以实现相同的功能。
我们再考虑另一种情况
a = 1 def func(): a = a+1 return a 这种也执行不会成功,因为a同样被认为是local变量,如何解决呢?与闭包类似,我们使用global(而不是nonlocal)来生命这个变量是全局变量
a = 1 def func(): global a a = a+1 return a 这种情况其实和闭包是很类似的,都是变量作用域的延伸。