>>> value = 27 >>> def func(param1,param2): for key,val in locals().items(): print (key,val) value = value + 1 >>> func(98765,43210) param1 98765 param2 43210 Traceback (most recent call last): File "<pyshell#7>", line 1, in <module> func(98765,43210) File "<pyshell#6>", line 4, in func value = value + 1 UnboundLocalError: local variable 'value' referenced before assignment >>>
首先經過賦值在全局命名空間中建立了變量value。也許你會認爲,當函數值加1是會先在局部的命名空間中查找變量,沒法找到時在全局命名空間中找到該名字。能夠並非這樣。
python提出以下假設,若是在函數體內的任何地方對變量賦值,則python將名稱添加到局部命名空間中。語句value=value+1對對象value進行賦值。python假設不管在何處發生賦值,value都是函數func局部命名空間的一部分。當python嘗試把1跟value相加時,該value名稱在局部命名空間中,但它沒有關聯值,因此python報錯。
問題在於python什麼時候決定使value出如今局部命名空間中。實際value出如今局部命名空間中發生在代碼運行前,即,在python運行到函數定義以前。因爲建立命名空間時,python會檢查代碼並填充局部命名空間。在python運行那行代碼以前,就發現了對value的賦值,並把它添加到局部命名空間中,當函數執行時,python解釋器認爲value在局部命名空間中但沒有值,因此會產生錯誤。
2.global語句
有一個方法能夠解決上面的問題。若是在函數體內,使用global語句將變量聲明爲全局變量,那麼python不會爲該變量在命名空間中建立局部名稱。
3、內置模塊
遵循LEGB搜索規則,若是python不能在局部命名空間中找到某個名稱,則會在全局命名空間中繼續尋找,它尋找到的將是python的內置名稱。
built-in模塊和其餘模塊同樣,都具備__dict__屬性,這就是模塊的命名空間
4、封閉式變量
「封閉式」的做用域規則適應於函數定義函數時,也就是說,在函數體內定義了一個新的函數。這個函數體內的函數是外函數的局部命名空間中的一部分,意味着只有在外函數執行期間纔可以運行。完整的LEGB規則是先檢查局部命名空間,以後是封閉在局部命名空間中的其餘函數,以後是全局命名空間,在最後之內置命名空間結束。
python