【ZZ】python命名空間與做用域

python命名空間與做用域

命名空間是名稱與對象之間的關係,能夠將命名空間看作是字典,其中的鍵是名稱,值是對象。

命名空間不共享名稱。

在命名空間中的名稱能將任何python對象做爲值,在不一樣的命名空間中相同的名稱能夠與不一樣的對象相關聯。可是,若是存在名稱解析協議,則多個命名空間能夠一塊兒工做來解析名稱。也就是說,若是有多個命名空間(老是有的),那麼能夠定義搜索的順序,依次在不一樣的命名空間裏來查找某個名稱(或確認其不存在於任何承認的命名空間)。在python中,將這一過程定義爲做用域。
做用域搜索規則:LEGB

L:局部的(local)

E:封閉的(Enclosing)

G:全局的(Global)

B:內置的(Built-in)
1、局部命名空間

函數內部的命名空間,在調用函數的時候生成,調用結束時消失。當局部命名空間有效時,它是第一個用於檢查某個名字存在性的命名空間。若是在局部命名空間內找到該名稱,則返回與名字相關聯的對象,反之提示出錯。
2、全局命名空間

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不會爲該變量在命名空間中建立局部名稱。
3、內置模塊

遵循LEGB搜索規則,若是python不能在局部命名空間中找到某個名稱,則會在全局命名空間中繼續尋找,它尋找到的將是python的內置名稱。

built-in模塊和其餘模塊同樣,都具備__dict__屬性,這就是模塊的命名空間
4、封閉式變量

「封閉式」的做用域規則適應於函數定義函數時,也就是說,在函數體內定義了一個新的函數。這個函數體內的函數是外函數的局部命名空間中的一部分,意味着只有在外函數執行期間纔可以運行。完整的LEGB規則是先檢查局部命名空間,以後是封閉在局部命名空間中的其餘函數,以後是全局命名空間,在最後之內置命名空間結束。
python

相關文章
相關標籤/搜索