Python3 名稱空間和作用域
導讀 |
名稱空間(Namespace)是從名稱到物件的對映,大部分的名稱空間都是透過 Python 字典來實現的。
作用域就是一個 Python 程式可以直接訪問名稱空間的正文區域。 |
名稱空間(Namespace)是從名稱到物件的對映,大部分的名稱空間都是透過 Python 字典來實現的。
名稱空間提供了在專案中避免名字衝突的一種方法。各個名稱空間是獨立的,沒有任何關係的,所以一個名稱空間中不能有重名,但不同的名稱空間是可以重名而沒有任何影響。
我們舉一個計算機系統中的例子,一個資料夾(目錄)中可以包含多個資料夾,每個資料夾中不能有相同的檔名,但不同資料夾中的檔案可以重名。
一般有三種名稱空間:
內建名稱(built-in names), Python 語言內建的名稱,比如函式名 abs、char 和異常名稱 BaseException、Exception 等等。
全域性名稱(global names),模組中定義的名稱,記錄了模組的變數,包括函式、類、其它匯入的模組、模組級的變數和常量。
區域性名稱(local names),函式中定義的名稱,記錄了函式的變數,包括函式的引數和區域性定義的變數。(類中定義的也是)
名稱空間查詢順序:
假設我們要使用變數 runoob,則 Python 的查詢順序為:區域性的名稱空間去 -> 全域性名稱空間 -> 內建名稱空間。
如果找不到變數 runoob,它將放棄查詢並引發一個 NameError 異常:
NameError: name 'runoob' is not defined。
名稱空間的生命週期:
名稱空間的生命週期取決於物件的作用域,如果物件執行完成,則該名稱空間的生命週期就結束。
因此,我們無法從外部名稱空間訪問內部名稱空間的物件。
例項 # var1 是全域性名稱 var1 = 5 def some_func(): # var2 是區域性名稱 var2 = 6 def some_inner_func(): # var3 是內嵌的區域性名稱 var3 = 7
如下圖所示,相同的物件名稱可以存在於多個名稱空間中。
作用域就是一個 Python 程式可以直接訪問名稱空間的正文區域。
在一個 python 程式中,直接訪問一個變數,會從內到外依次訪問所有的作用域直到找到,否則會報未定義的錯誤。
Python 中,程式的變數並不是在哪個位置都可以訪問的,訪問許可權決定於這個變數是在哪裡賦值的。
變數的作用域決定了在哪一部分程式可以訪問哪個特定的變數名稱。Python的作用域一共有4種,分別是:
有四種作用域:
L(Local):最內層,包含區域性變數,比如一個函式/方法內部。
E(Enclosing):包含了非區域性(non-local)也非全域性(non-global)的變數。比如兩個巢狀函式,一個函式(或類) A 裡面又包含了一個函式 B ,那麼對於 B 中的名稱來說 A 中的作用域就為 nonlocal。
G(Global):當前
的最外層,比如當前模組的全域性變數。
B(Built-in): 包含了內建的變數/關鍵字等。,最後被搜尋
規則順序: L –> E –> G –>gt; B。
在區域性找不到,便會去區域性外的區域性找(例如閉包),再找不到就會去全域性找,再者去內建中找。
g_count = 0 # 全域性作用域 def outer(): o_count = 1 # 閉包函式外的函式中 def inner(): i_count = 2 # 區域性作用域
內建作用域是透過一個名為 builtin 的標準模組來實現的,但是這個變數名自身並沒有放入內建作用域內,所以必須匯入這個檔案才能夠使用它。在Python3.0中,可以使用以下的程式碼來檢視到底預定義了哪些變數:
>>> import builtins >>> dir(builtins)
Python 中只有模組(module),類(class)以及函式(def、lambda)才會引入新的作用域,其它的程式碼塊(如 if/elif/else/、try/except、for/while等)是不會引入新的作用域的,也就是說這些語句內定義的變數,外部也可以訪問,如下程式碼:
>>> if True: ... msg = 'I am from Runoob' ... >>> msg 'I am from Runoob' >>>
例項中 msg 變數定義在 if 語句塊中,但外部還是可以訪問的。
如果將 msg 定義在函式中,則它就是區域性變數,外部不能訪問:
>>> def test(): ... msg_inner = 'I am from Runoob' ... >>> msg_inner Traceback (most recent call last): File "", line 1, inNameError: name 'msg_inner' is not defined >>>
從報錯的資訊上看,說明了 msg_inner 未定義,無法使用,因為它是區域性變數,只有在函式內可以使用。
定義在函式內部的變數擁有一個區域性作用域,定義在函式外的擁有全域性作用域。
區域性變數只能在其被宣告的函式內部訪問,而全域性變數可以在整個程式範圍內訪問。呼叫函式時,所有在函式內宣告的變數名稱都將被加入到作用域中。如下例項:
例項(Python 3.0+) #!/usr/bin/python3 total = 0 # 這是一個全域性變數 # 可寫函式說明 def sum( arg1, arg2 ): #返回2個引數的和." total = arg1 + arg2 # total在這裡是區域性變數. print ("函式內是區域性變數 : ", total) return total #呼叫sum函式 sum( 10, 20 ) print ("函式外是全域性變數 : ", total)
以上例項輸出結果:
函式內是區域性變數 : 30 函式外是全域性變數 : 0
當內部作用域想修改外部作用域的變數時,就要用到global和nonlocal關鍵字了。
以下例項修改全域性變數 num:
例項(Python 3.0+) #!/usr/bin/python3 num = 1 def fun1(): global num # 需要使用 global 關鍵字宣告 print(num) num = 123 print(num) fun1() print(num)
以上例項輸出結果:
1 123 123
如果要修改巢狀作用域(enclosing 作用域,外層非全域性作用域)中的變數則需要 nonlocal 關鍵字了,如下例項:
例項(Python 3.0+) #!/usr/bin/python3 def outer(): num = 10 def inner(): nonlocal num # nonlocal關鍵字宣告 num = 100 print(num) inner() print(num) outer()
以上例項輸出結果:
100 100
另外有一種特殊情況,假設下面這段程式碼被執行:
例項(Python 3.0+) #!/usr/bin/python3 a = 10 def test(): a = a + 1 print(a) test()
以上程式執行,報錯資訊如下:
Traceback (most recent call last): File "test.py", line 7, intest() File "test.py", line 5, in test a = a + 1 UnboundLocalError: local variable 'a' referenced before assignment
錯誤資訊為區域性作用域引用錯誤,因為 test 函式中的 a 使用的是區域性,未定義,無法修改。
修改 a 為全域性變數,透過函式引數傳遞,可以正常執行輸出結果為:
例項(Python 3.0+) #!/usr/bin/python3 a = 10 def test(a): a = a + 1 print(a) test(a)
執行輸出結果為:
11
原文來自:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2671525/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Python作用域和名稱空間Python
- Python名稱空間和作用域窺探Python
- python基礎 - python名稱空間與作用域Python
- .NET C#基礎(6):名稱空間 - 有名字的作用域C#
- 名稱空間
- 使用p名稱空間和c名稱空間的XML快捷方式XML
- JAXB名稱空間及名稱空間字首處理
- PHP 名稱空間PHP
- PHP名稱空間PHP
- vuex名稱空間Vue
- jQuery 名稱空間jQuery
- JavaScript 名稱空間JavaScript
- XML和Schema名稱空間詳解XML
- 內聯和巢狀名稱空間巢狀
- python名稱空間Python
- C++名稱空間C++
- 更改模型名稱空間模型
- 全域性名稱空間
- C++ 名稱空間C++
- Python 名稱空間Python
- 11. 名稱空間
- ts---名稱空間
- k8s中名稱空間的作用是什麼K8S
- PHP 核心特性 - 名稱空間PHP
- Spring名稱空間解析Spring
- 使用名稱空間:基礎
- ros節點名稱空間ROS
- JavaScript 中的名稱空間JavaScript
- PHP名稱空間概念解析PHP
- JAXB玩轉名稱空間
- Python 的名稱空間Python
- System.Web 名稱空間Web
- Python名稱空間包Python
- C和C++中的名字空間和作用域C++
- Python中名稱空間是什麼?名稱空間生命週期是多久?Python
- System.Security.Cryptography 名稱空間
- c++系列:匿名名稱空間C++
- Objective-C 的名稱空間Object