Python3.x那些事兒:[63]作用域和名稱空間?

名稱空間是從名字到物件的一組對映。大部分的名稱空間目前都是使用Python的字典型別來實現的,但是並沒有進行規定(除非是為了效能考慮),這種情況可能會在將來有所改變。例如:內建名稱的集合(包含函式和內建異常型別);一個模組中的全域性名稱;一個函式呼叫過程中的本地名稱。從某種意義上來說一個物件中的所有屬性的集合也構成一個名稱空間。在名稱空間中需要知道的一個重要事實是在不同的名稱空間中名字之間是沒有任何關係的,例如,兩個不同的模組都定義了一個函式maximize,但是它們並不會發生衝突。

同時,任何一個.後面跟著的名稱都被稱為屬性,例如,在z.real表示式中,real是物件z的一個屬性。嚴格來說,對模組中名字的引用都是屬性引用,在表示式modname.funcname中,modname是一個模組物件,funcname是它的一個屬性。在這裡剛好有一個模組屬性與模組中全域性名字的對映,因此它們使用的是同一個名稱空間。有一件事情是個例外,模組物件中有一個祕密的只讀屬性叫做__dict__,它返回一個字典型別用來實現模組中的名稱空間。__dict__是一個屬性但是不是一個全域性名稱。顯然,使用這個東西違反了名稱空間實現的抽象性原則,因此要嚴格控制使用,只有在某些偵錯程式中可以使用。

屬性可以使只讀或者是可寫的。在可寫情況下,給屬性賦值是可以的。模組屬性都是可寫的。你可以寫:modname.the_answer=42。可寫屬性也可以使用del語句刪掉。例如,del modname.the_answer會刪除modname模組中的the_answer屬性。

名稱空間會在不同的時間建立,並有不同的生命週期。包含內建名稱的名稱空間是在python直譯器啟動的時候建立的,並且不會被刪除。一個模組的全域性名稱空間是在模組定義程式碼被讀入的時候建立的,一般情況下,模組名稱空間會持續到直譯器結束。在直譯器最上層呼叫的程式碼,不管是從指令碼中讀入的還是在互動式介面中,都會被認為是屬於一個叫做__main__模組的,所以它們有自己的全域性名稱空間。(內建名稱實際上也放置在一個模組中,稱為builtins)。

函式的本地名稱空間會在函式被呼叫的時候被建立,當函式返回或者是出現異常並且沒有被函式處理的時候被刪除。當然遞迴呼叫的每一次呼叫都會產生一個獨立的本地名稱空間。

作用域是一個Python程式中名稱空間能夠直接接觸到的部分。也就是說直接用名字進行引用就可以使用的名稱空間。

雖然作用域是靜態確定的,實際上他們是動態的。執行時的任何時間,都會存在三個巢狀的作用域:

1、最內層作用域,會被最先查詢,包含本地名稱。

2、函式作用域,包含非本地,但是也非全域性的名稱。

3、包含模組全域性名稱的作用域。

4、最外層的作用域,包含內建名稱。

如果一個名稱被宣告為global,那麼所有的引用和賦值都會直接作用於模組全域性名稱。為了將一個外部變數重新繫結到外部,則可以使用nonlocal關鍵字。如果沒有宣告nonlocal,這些變數就是隻讀的(試圖去寫一個這樣一個變數會在內層作用域中重新建立一個新的本地變數)。

通常,本地作用域會引用當前函式的本地變數。

Python3.x那些事兒 (共69篇) 上一篇:名字和物件 下一篇:作用域和名稱空間...

空間, 事兒, 作用域,
相關問題答案