Python中inner function的binding處理

BBS上的一個帖子,問題是
def a():
    
def b():
        x 
+= 1
 
    x 
= 1
    
print "a: ", x
    b()
    
print "b: ", x
 
def c():
    
def d():
        x[0] 
= [4]
    x 
= [3]
    
print "c: ", x[0]
    d()
    
print "d: ", x[0]

運行a()會報UnboundLocalError: local variable ‘x’ referenced before assignment
但是運行c()會正確地顯示3和4。

原因在於原因在於CPython實現closure的方式和常見的functional language不同,採用了flat closures實現。

“If a name is bound anywhere within a code block, all uses of thename within the block are treated as references to the current block.”

在第一個例子中,b函數x += 1對x進行賦值,rebind了這個對象,於是Python查找x的時候只會在local environment中搜索,於是就有了UnboundLocalError。

換句話說,如果沒有修改這個值,比如b中僅僅簡單的輸出了x,程序是可以正常運行的,因爲此時搜索的範圍是nearest enclosing function region。

而d方法並沒有rebind x變量,只是修改了x指向的對象的值而已。如果把賦值語句改成x = [4],那麼結果就和原來不一樣了,因爲此時發生了x的rebind。

所以Python中的closure可以理解爲是隻讀的。

另外第二個例子也是這篇文章中提到的一種workaround:把要通過inner function修改的變量包裝到數組裏,然後在inner function中訪問這個數組。

至於爲什麼Python中enclosed function不能修改enclosing function的binding,文中提到了主要原因還是在於Guido反對這麼做。因爲這樣會導致本應該作爲類的實例保存的對象被聲明瞭本地變量。

參考網站:http://www.python.org/dev/peps/pep-0227/


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