python基礎 - python名稱空間與作用域

pythontab發表於2013-03-11

名稱空間是名稱與物件之間的關係,可以將名稱空間看做是字典,其中的鍵是名稱,值是物件。

名稱空間不共享名稱。

在名稱空間中的名稱能將任何python物件作為值,在不同的名稱空間中相同的名稱可以與不同的物件相關聯。但是,如果存在名稱解析協議,則多個名稱空間可以一起工作來解析名稱。也就是說,如果有多個名稱空間(總是有的),那麼可以定義搜尋的順序,依次在不同的名稱空間裡來查詢某個名稱(或確認其不存在於任何認可的名稱空間)。在python中,將這一過程定義為作用域。

作用域搜尋規則:LEGB

L:區域性的(local)

E:封閉的(Enclosing)

G:全域性的(Global)

B:內建的(Built-in)

一、區域性名稱空間

函式內部的名稱空間,在呼叫函式的時候生成,呼叫結束時消失。當區域性名稱空間有效時,它是第一個用於檢查某個名字存在性的名稱空間。如果在區域性名稱空間內找到該名稱,則返回與名字相關聯的物件,反之提示出錯。

二、全域性名稱空間

python在模組中維護名稱空間,模組是一些python檔案--包含函式等物件,並且可以匯入其他程式使用。當某個模組被匯入之後,該模組同時引入了一個名稱空間,其中包含模組中所有的名稱和關聯的物件,可以透過儲存在沒個模組中的__dict__來檢視這個名稱空間,換句話說,字典就是這個模組的名稱空間。

如果想要引用給模組中的物件,要使用點符號將名稱和模組名稱關聯,這實際上是要求將物件與該模組中的名稱相關聯。

當python啟動直譯器時,它將自動匯入兩個模組,即模組__main__和__built-ins__。__main__模組是預設的全域性模組,所有新物件都儲存在其中。可以透過函式globals來訪問該名稱空間的字典。子啊平python直譯器中透過輸入使用者互動時,globals是有效的名稱空間。

1.區域性賦值規則

python中有一種稱為“本地賦值”的規則非常有趣。如果在函式內的任何地方進行區域性賦值,則該賦值只在當前活動的名稱空間中建立名稱。有時這將產生副作用,舉例如下:

>>> 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不會為該變數在名稱空間中建立區域性名稱。

三、內建模組

遵循LEGB搜尋規則,如果python不能在區域性名稱空間中找到某個名稱,則會在全域性名稱空間中繼續尋找,它尋找到的將是python的內建名稱。

built-in模組和其他模組一樣,都具有__dict__屬性,這就是模組的名稱空間

四、封閉式變數

“封閉式”的作用域規則適應於函式定義函式時,也就是說,在函式體內定義了一個新的函式。這個函式體內的函式是外函式的區域性名稱空間中的一部分,意味著只有在外函式執行期間才能夠執行。完整的LEGB規則是先檢查區域性名稱空間,之後是封閉在區域性名稱空間中的其他函式,之後是全域性名稱空間,在最後以內建名稱空間結束。


相關文章