详解python函数的闭包问题(内部函数与外部函数详述)
python函数的闭包问题(内嵌函数)
>>> def func1(): ... print ('func1 running...') ... def func2(): ... print ('func2 running...') ... func2() ... >>> func1() func1 running... func2 running...
内部函数func2作用域都在外部函数func1作用域之内
如果试图在外部函数的外部调用内部函数将会报错
>>> func2() Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'func2' is not defined
关于python的闭包问题
如果试图在一个内部函数里对外部作用域(不包括外部函数的外部作用域)的变量进行引用,内部函数就会被认为是闭包
>>> def FuncX(x): ... def FuncY(y): ... return x*y ... return FuncY
对于FuncY函数来说,对在FuncX函数的整个作用域(FuncY函数的非全局作用域的外部作用)的变量x进行引用,自此就可以说FuncY函数就是所谓的闭包
>>> f = FuncX(8) >>> f <function FuncY at 0x7f3a436fc2a8> >>> type(f) <type 'function'> >>> f(10) 80 >>> FuncX(7)(8) 56
由于闭包本身是基于内部函数这一概念而来,所以不能在外部函数的外部作用域对内部函数进行调用
>>> FuncY(8) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'FuncY' is not defined
既然是基于内部函数这一概念而来,自然对于内部函数来说对引用外部函数作用域内的变量进行修改,将会启动解释器的屏蔽机制
>>> def Func1(): ... x = 233 ... def Func2(): ... x *=x ... return x ... return Func2() ... >>> Func1() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 6, in Func1 File "<stdin>", line 4, in Func2 UnboundLocalError: local variable 'x' referenced before assignment
x*=x的左值此时是内部函数作用域里的变量,此时试图将没有定义的数据进行平方操作,因此报错
>>> def Func1(): ... x = 233 ... def Func2(): ... x = 321 ... return x ... return Func2() ... >>> Func1() 321
内部函数创建x变量并且屏蔽外部函数作用域内的x变量
python3之前的解决办法
应用容器类型(list,tuple之类的)存放外部函数作用域的变量从而不会被屏蔽机制屏蔽掉,因为容器类型不是存放在栈里面
>>> def Func1(): ... x = [233] ... def Func2(): ... x[0] *= x[0] ... return x[0] ... return Func2() ... >>> Func1() 54289
python3之后的解决办法:nonlocal关键字
>>> def Func1(): ... x = 233 ... def Func2(): ... nonlocal x ... x *= x ... return x ... return Func2() ... >>> Func1() 54289