Python學習筆記:作用域和命名空間

本篇參考官方文檔: The Python Tutorial 9.2: Python Scopes and Namespaces

這節非常重要,許多錯誤都是對作用域和命名空間不熟悉導致的。先看看文檔裏對命名空間(namespace)的定義:

命名空間是從名字到對象的映射。大多數命名空間目前是由Python字典實現的。例子有:內建(built-in)名字(比如abs()函數);一個模塊裏的全局名字,一個函數裏的本地名字。某種意義上對象的屬性(attribute)也形成了命名空間。不同命名空間裏的名字之間沒有關係;比如,兩個不同的模塊可能都定義了函數maximize而不產生困擾—模塊的用戶必須加上模塊名前綴。

名字和對象也是非常重要的概念,參考Python學習筆記:對象,值和類型。簡而言之名字是變量的標識符,也是引用。任何尾隨點(.)的名字都叫做屬性。比如,在z.real中,real是對象z的一個屬性。attribute作動詞還有“歸屬”,“把…歸於”的意思,所以把尾隨點(.)的名字都叫做屬性是很合理的。命名空間的概念源自編譯原理的符號表(symbol table)

接下來講命名空間的創建和刪除:

命名空間可以在不同的時刻創建,而且有不同的壽命。包含內建名字的命名空間在Python解釋器啓動一開始就創建了,永不被刪除。一個模塊的全局命名空間在模塊被讀進的時候創建,通常也持續到解釋器停止。
一個函數的本地命名空間在函數被調用的時候創建,函數返回或拋出異常的時候刪除。


接下來該說作用域了:

一個作用域是一個Python程序的文本區域(textual region),在這裏一個命名空間是直接可訪問的(directly accessible)。“直接可訪問”的意思是一個未經限定(unqualified)的變量引用試圖在命名空間裏尋找這個變量。

這段就比較費解了,有很多莫名其妙的詞。文本區域指的是程序代碼中的某一塊,作用域規定了在這一文本區域哪些命名空間會發生作用。打個比方,作用域就是一個縣規章制度,它規定了所轄各個鎮的居民的名字和電話號的對應關係。比如你是牽牛鄉的,想查小紅的電話號,作用域會甩給你牽牛鄉的電話本。如果你想查紅旗鎮的小紅的電話號,不好意思,不可以。

雖然作用域被全局地確定,但是被動態地使用。在程序執行的任何時間,至少有三種嵌套的作用域,它們的命名空間是直接可訪問的:
- 最裏面那層的作用域,被最先搜索,它包含了本地名字。
- 封閉(enclosing)函數的作用域,從最近的(nearest)封閉作用域開始搜索,包含了非本地、非全局地名字。
- 倒數第二的作用域包含了當前模塊的全局名字。
- 最外層的作用域(最後搜索) 是內建名字的命名空間。

作用域又可理解成權限,一塊代碼對哪些命名空間有權限。封閉函數是內部有至少另一個函數定義的函數,跟Java的內部類有點像。

如果一個名字被聲明成global,那麼所有的引用和賦值都直接在中層的包含此模塊的全局名字的作用域發生。否則,所有在最裏層作用域之外發現的變量都是隻讀的(寫這種變量僅僅會在最裏層作用域創建一個新的本地變量)。
同常,本地作用域聯繫着當前函數的本地變量。在函數之外,本地作用域就聯繫着跟全局作用域相同的命名空間了。

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