python-作用域
- 名稱空間
名稱空間(Namespace)是從名稱到物件的對映,大部分的名稱空間都是通過 Python 字典來實現的
名稱空間提供了在專案中避免名字衝突的一種方法
各個名稱空間是獨立的,沒有任何關係的,所以一個名稱空間中不能有重名,但不同的名稱空間是可以重名而沒有任何影響
包括內建名稱(built-in names,python本身定義的名稱),全域性名稱(global names,模組中定義的名稱),區域性名稱(local names,函式中定義的名稱)
如果要使用變數 runoob,則 Python 的查詢順序為:區域性的名稱空間去 -> 全域性名稱空間 -> 內建名稱空間
如果找不到變數 runoob,它將放棄查詢並引發一個 NameError 異常
# var1 是全域性名稱
var1 = 5
def some_func():
# var2 是區域性名稱
var2 = 6
def some_inner_func():
# var3 是內嵌的區域性名稱
var3 = 7
名稱空間的生命週期取決於物件的作用域,如果物件執行完成,則該名稱空間的生命週期就結束。
因此,我們無法從外部名稱空間訪問內部名稱空間的物件。
- 作用域
L(Local):最內層,包含區域性變數,比如一個函式/方法內部
E(Enclosing):包含了非區域性(non-local)也非全域性(non-global)的變數。比如兩個巢狀函式,一個函式(或類) A 裡面又包含了一個函式 B ,那麼對於 B 中的名稱來說 A 中的作用域就為 nonlocal
G(Global):當前指令碼的最外層,比如當前模組的全域性變數
B(Built-in): 包含了內建的變數/關鍵字等,最後被搜尋
Python 中只有模組(module),類(class)以及函式(def、lambda)才會引入新的作用域(其內的變數為區域性變數,外部無法呼叫,使用的時候是通過傳參的方式)
其它的程式碼塊(如 if/elif/else/、try/except、for/while等)是不會引入新的作用域的,也就是說這些語句內定義的變數,外部也可以訪問
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 = 1
def fun1():
global num # 需要使用 global 關鍵字宣告
print(num)
num = 123
print(num)
fun1()
print(num)
# 1
# 123
# 123
在函式的開頭使用global表明使用的是全域性num變數,後續的檢視和操作都是針對於這個全域性變數(此處沒有建立新的變數)
def outer():
num = 10
def inner():
nonlocal num # nonlocal關鍵字宣告
num = 100
print(num)
inner()
print(num)
outer()
# 100
# 100
使用nonlocal表明使用的是外層巢狀函式的變數
a = 10
def test():
global a
a = a + 1
print(a)
test()
# 11
如果不設定global,則會出現函式內a為定義的錯誤
a = 10
def test(a):
a = a + 1
print(a)
test(a)
# 11
也可以使用傳遞的引數