命名空間,又名 namesapce
,是在不少的編程語言中都會出現的術語,估計不少人都知道這個詞,可是讓你真的來講這是個什麼,估計就歇菜了,因此我以爲「命名空間」 有必要了解一下。python
全局變量和局部變量是咱們理解命名空間的開始,咱們先來看一段代碼:編程
x = 2
def func():
x = 3
print('func x ---> ',x)
func()
print('out of func x ---> ',x)
複製代碼
這段代碼輸出的結果以下:bash
func x ---> 3
out of func x ---> 2
複製代碼
從上述的結果中能夠看出,運行 func(),輸出的是 func() 裏面的變量 x 所引用的對象 3,以後執行的是代碼中的最後一行。這裏要區分清楚,前一個 x 輸出的是函數內部的變量 x,後一個 x 輸出的是函數外的變量 x,兩個變量互相不影響,在各自的做用域中起做用。編程語言
那個只在函數內起做用的變量就叫「局部變量」,有了「局部」就有相應的 「所有」,可是後者聽起來有歧義,因此就叫了「全局」。模塊化
x = 2
def func():
global x = 3 #注意此處
print('func x ---> ',x)
func()
print('out of func x ---> ',x)
複製代碼
這段代碼中比上段代碼多加了一個 global x
,這句話的意思是在聲明 x 是全局變量,通俗點說就是這個 x 和 函數外的 x 是同一個了,因此結果就成了下面這樣:函數
func x ---> 3
out of func x ---> 3
複製代碼
這樣乍一看好像全局變量好強,能夠管着函數內外,可是咱們仍是要注意,全局變量仍是謹慎使用的好,由於畢竟內外有別,不要帶來混亂。ui
做用域,用比較直白的方式來講,就是程序中變量與對象存在關聯的那段程序,好比我在上面說的, x = 2 和 x = 3 是在兩個不一樣的做用域中。spa
一般的,做用域是被分爲靜態做用域和動態做用域,雖然咱們說 Python 是動態語言,可是它的做用域屬於靜態做用域,即 Python 中的變量的做用域是由該變量所在程序中的位置所決定的。code
在 Python 中做用域被劃分紅四個層級,分別是:local(局部做用域),enclosing(嵌套做用域),global(全局做用域)和 built - in(內建做用域)。對於一個變量,Python 也是按照以前四個層級依次在不用的做用域中查找,咱們在上一段代碼中,對於變量 x,首先搜索的是函數體內的局部做用域,而後是函數體外的全局做用域,至於這段話具體怎麼來理解,請看下面的例子:cdn
def out_func():
x = 2
def in_func():
x = 3
print('in_func x ---> ',x)
in_func()
print('out_func x ---> ',x)
x = 4
out_func()
print('x == ',x)
複製代碼
上述代碼運行的結果是:
in_func x ---> 3
out_func x ---> 2
x == 4
複製代碼
仔細觀察一下上面的代碼和運行的結果,你就會發現變量在不一樣的範圍內進行搜索的規律,是否是感受這些都是之前被你忽略的呢?
《維基百科》中說「命名空間是對做用域的一種特殊的抽象」,在這裏我用一個比方來具體說明一下:
好比張三在公司 A,他的工號是 111,李四在公司 B,他的工號也是 111,由於兩我的在不一樣的公司,他們倆的工號能夠相同可是不會引發混亂,這裏的公司就表示一個獨立的命名空間,若是兩我的在一個公司的話,他們的工號就不能相同,不然光看工號也不知道究竟是誰。
其實上面舉的這個例子的特色就是咱們使用命名空間的理由,在大型的計算機程序中,每每會出現成百上千的標識符,命名空間提供隱藏區域標識符的機制。經過將邏輯上相關的標識符構成響應的命名空間,可使整個系統更加的模塊化。
我在開頭引用的《維基百科》的那句話說 「命名空間是對做用域的一種特殊的抽象」,它其實包含了處於該做用域內的標識符,且它自己也用一個標識符來表示。在 Python 中,命名空間自己的標識符也屬於更外層的一個命名空間,因此命名空間也是能夠嵌套的,它們共同生活在「全局命名空間」下。
簡言之,不一樣的命名空間能夠同時存在,可是彼此獨立,互不干擾。固然了,命名空間由於其對象的不一樣也有所區別,能夠分爲如下幾種:
本地命名空間:模塊中有函數或者類的時候,每一個函數或者類所定義的命名空間便是本地命名空間,當函數返回結果或者拋出異常的時候,本地命名空間也就結束了。
全局命名空間:每一個模塊建立了本身所擁有的全局命名空間,不一樣模塊的全局命名空間彼此獨立,不一樣模塊中相同名稱的命名空間也會由於模塊的不一樣而不相互干擾。
內置命名空間:當 Python 運行起來的時候,它們就存在了,內置函數的命名空間都屬於內置命名空間,因此咱們能夠在任何程序中直接運行它們。
程序查詢命名空間的時候也有一套順序,依次按照本地命名空間 ,全局命名空間,內置命名空間。
def fun(like):
name = 'rocky'
print(locals())
fun('python')
複製代碼
訪問本地命名空間使用 locals 完成,咱們來看一下結果:
{'name': 'rocky', 'like': 'python'}
複製代碼
從上面的結果中能夠看出,命名空間中的數據存儲的結構和字典是同樣的。可能你已經猜到了,當咱們要訪問全局命名空間的時候,可使用 globals。
關於命名空間還有一個生命週期的問題,就是一個命名空間何時出現,何時消失,這個很好理解,就是哪部分被讀入內存,哪部分的命名空間就存在了,好比咱們在上面說的,Python 啓動,內置命名空間就創建。
更多內容,歡迎關注公衆號「Python空間」,期待和你的交流。