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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章