459
Namespace(命名空間)、Scope(作用域)
這兩個專有名詞關係著變數存取的問題。
什麼是Namespace ?
即名稱到物件的映射。直接敘述很抽象,請見以下範例
#範例 1
x = 2
上式是指定x的變數,儲存整數2的值。
當設定變數時,在python裡會有一本字典存取設定過的變數、函試名稱,以供後面程式碼區要使用變數時能訪問。
那個空間就是Namespace,一個文檔中在不同的區塊會同時有多個不一樣的Namespace供參考訪問。
命名空間的例子有:
- 內建名稱的集合(包含如
[abs()](<https://docs.python.org/zh-tw/3/library/functions.html#abs>)的函式) - 模組中的全域 (global) 名稱(即調用模組裡的變數)
- 函式調用中的區域 (local) 名稱
- 在模組中,使用屬性 (attribute) 這個字,統稱句號 (dot) 後面的任何名稱,也算是一種Namespace
Namespace可隨時建立,並且有不同的持續時間,例如 :
- 內建的命名空間 : Python 內建命名集合,當python直譯器啟動時,會立刻建立,且不會刪除。
- 引入模組的全域名稱 : 在當前模組下的命名集合,當模組定義被讀入時,模組的全域命名空間會被建立,通常會持續到直譯器結束
- 函式裡的區域名稱 : 在某個函式或者類方法裡面的本地名稱集合,函式的區域命名空間是在呼叫函式時建立的,而當函式返回,或引發了未在函式中處理的例外時,此命名空間將會被刪除。
簡而言之,Namespace就是一本本字典,裡面記載著我們設定過的名稱,以及對應它的內容。
他們有不同的建立時間、層級與持續時間,讓我們在不同的時刻訪問他來提取我們需要的內容,一份文件裡可能同時有多個不同的字典在應用,那python裡式如何分類他們不同的使用場所與時機,那便是下一個問題。
什麼是Scope(作用域)?
Python 程式中的某一段或某些段文本區域 (textual region),在此區域,命名空間中的名稱是可”直接存取/直接訪問”的。
#範例 2
#以下是根據查看的文章對文本區域一詞的了解
一個define裡,也能當作一個作用場域。
def a() :
A=123
print(A)
存取(訪問)的方式有以下兩種 :
- 屬性訪問 : 所有名字後加 . 的都認為是屬性訪問。
- 存取訪問 : 可直接存取引用變數名,不須屬性訪問的。
#範例 3
#需要從某個模組指定 func_name
module_name.func_name
#直接訪問內建的函式
abs(-1)
程式執行中常見的幾個作用域 :
- 局部作用域(Local,L) : 包含區域性變數,最內層作用域,會最先被搜尋。Ex : 函式內部
- 嵌套作用域(Enclosing,E) : 包含了非區域性(non-local)也非全域性(non-global)的變數。 任何外圍函式 (enclosing function) 的作用域,會從最近的外圍作用域開始搜尋。 Ex : 見於兩個巢狀函式,內層函式可能搜尋外層函式的namespace,但該namespace對內層函式而言既非區域性也非全域性。 Ex : class裡的變數能用在下面的方法,但不能用到上一層的文件檔中也算,但方法能繼承初始變數這不曉得算不算(self.a這種的不曉得算不算,我覺得應該不算)
- 全局作用域(Global,G) : 在一個.py文件檔裡,最外層直接命名的名稱。
- 內置作用域(Built-in,B) : python內建的名稱與函式庫。
名稱調用順序為 : L→E→G→B,以下為理解範例 :
#範例 4
#在函式裡作用域的名稱空間調用順序
b=224
def A():
a=123
print (a,b)
"""
函式名稱 print()的尋找過程
局部作用域(X)->嵌套作用域(X)->全局作用域(X)->內置作用域(V)
名稱 a 的尋找過程
局部作用域(V)
名稱 b 的尋找過程
局部作用域(X)->全局作用域(V)
"""
A()
#執行結果
# >>> 123,224
#範例 5
#在多重嵌套函式裡的命名空間調用
#在外層函數F5()裡建立內層函數F()並呼叫,同時寫進
a = 1 #記錄在全局作用域的名稱空間
def F5():
def F(): # a不是F的區域性變數,那就繼承上層函式中a的屬性
print("In F5's F,a =", a)
a = 3
F()
F5()
函式名稱 print()的尋找過程
局部作用域(X)->嵌套作用域(X)->全局作用域(X)->內置作用域(V)
名稱 a 的尋找過程
局部作用域(X)->嵌套作用域(V)
#執行結果
# >>> In F5’s F,a = 3
print (a)
此處名稱 a 的尋找過程,因為並沒有包在函式與嵌套函式內
全局作用域(V)
#執行結果
# >>> 1
#範例 6
class test:
b = 1
def __init__(self):
self.a = 0
def myfun2(self):
self.a += 1
print("a = ", self.a)
self.b += 1
print("b = ", self.b)
test = test()
test.myfun2()
b算是嵌套式作用域取得的
但self.a我覺得不太算,因為它是用屬性訪問到
#输出结果:
# >>> a = 1
# >>> b = 2`
相關問題回顧 :
- 什麼是全局變數、什麼是區域變數、還有其他種類嗎 ?
- 文件裡創建變數後,能否在def裡面直接訪問 ?
- Class的屬性,能否當作一種Namespace ?
- 訪問/提取 有幾種方式 ?
- 作用域查找的順序 ?
