先解释一下闭包的概念:
我们定义了一个函数,称它为外函数,在外函数的内部定义了内函数,然后内函数使用了外函数的局部变量,并且外函数返回的是内函数。这种情况就是闭包。
def Outer(a): #外函数以及外函数的局部变量a
def Inner(): #内函数
print(a) #引用了外函数的局部变量
return Inner #返回了内函数
demo = Outer(5)
demo() #输出5
demox = Outer(3)
demox() #输出3
应该能明白啥叫闭包了吧,我们继续。。。。
现在我们要先讨论一下关于函数调用的问题,在我们的概念中,函数调用完成之后所有局部变量都是要销毁的,但是在闭包中有些特殊,执行完外函数之后,python发现内函数还使用了外函数的变量,于是就把这个变量给了内函数,以至于内函数可以继续使用。
但~~~~是,你会发现无法修改外函数的变量,这可怎么办???
好吧,其实有两种方法可以实现修改:
- python3中,可以把变量声明称nonlocal,这样的话就可以修改了
- python2中可没有nonlocal,所以可以把变量转化成可修改的数据类型,例如转化成一个列表
def Outer(a): #外函数以及外函数的局部变量a
b = 0
b = [b] #采用了第二种方法
def Inner(x): #内函数
nonlocal a #采用了第一种方法
a += x
b[0] += x
print(a)
return Inner #返回了内函数
demo = Outer(5)
demo(3) #输出8
demo(4) #输出12
demo1 = Outer(3)
demo2 = Outer(3)
这个跟文章开始的那个差不多,用了声明nonlocal的方法去修改a,转换数据类型的方法去修改b。
发现了没有,在我第二次调用demo函数的时候a不再是5了,而是8,说明什么??说明a相对于demo函数是静态的,每调用一次函数都会发生改变。看最后两行代码,如果这样的话,demo1和demo2之间的a值是互不干扰的。