名稱空間和作用域
阿新 • • 發佈:2021-08-04
作用域,就是 python 程式中,可以直接訪問名稱空間的正文區域。
python 中程式的變數也是有作用範圍的,在範圍之外是不能訪問的,能訪問的範圍決定於變數定義/賦值的位置。
區域性作用域(Local,最內層,函式或閉包函式內,包含區域性變數)
閉包函式外的作用域(Enclosing),主要就是巢狀函式中閉包函式外的區域,包含非區域性(non-local)也非全域性(non-global的變數)
全域性作用域(glocal),當前程式的最外層區域,包含本程式檔案/模組的全域性變數
內建作用域(built-in)包含了內建函式、關鍵字等。在使用一個變數的時候,會按照由內而外的順序取尋找該變數的定義,內層可遮蔽外層
num1=123 #全域性作用域變數
def fun():
num1=234 # 閉包函式外的函式中變數
def fun1():
num1=345 #區域性作用域變數
python 中只有模組(module)、類(class)以及函式(def、lambda)能引入新的作用域
其他語句塊是不會引入新的作用域的,如 if…else… 、try…except…和 for/while等
def fun(): inner=21 list1=[1,2,3,4] a='abcdef' for i in list1: a+=a[i] print(i) #這裡是可以使用i的,因為i在for中定義了,for不形成新作用域 print(a) # print(inner) #這裡會報錯,因為inner只在函式fun中定義了,在函式外沒定義,所以找不到inner變數
global 和 nonlocal 關鍵字
global 用在區域性作用域或閉包函式外的函式作用域中,用來指出在該作用域中使用的變數是全域性變數,而非區域性變數,該變數可以是在全域性作用域中出現過的變數,也可以是沒出現過的變數。
但是必須在第一次使用之前宣告,否則就會報錯
num = 0 # 這是一個全域性變數
def fun1():
num =2
# global num # 函式內,在global宣告之前已經使用過num.這裡會報錯
print ("函式內: ", num)
return num
fun1()
print ("函式外: ", num)
nonlocal 用在閉包函式內的函式作用域中
若閉包函式外的函式中沒有此同名變數則會報錯
num = 0 # 這是一個全域性變數
def fun1():
# global num
num = 1 # num 在這裡是全域性變數.
def fun2():
nonlocal num # 這裡會報錯,因為在外層函式中沒有同名區域性變數;註釋掉global num就不會報錯了
num=2
print("閉包函式內: ", num)
return num
fun2()
print ("函式內: ", num)
return num
fun1()
print ("函式外: ", num)
緣由
不可變型別
總的來說對於不可變型別:像 int 、 float 、 str 等型別;
定義即賦值,修改實際上是新的定義,這一類變數的定義和修改都是使用賦值運算子 '='。
可變型別
像 list 、 set 、 dict 等型別是一類可變型別,所謂可變型別,就是定義之後,還可以對變數進行修改,修改前後,
該變數的 id 不變,這一類變數定義使用賦值運算子,
修改則需要下標(或鍵),還可以有插入、刪除等操作。
list1=['a','b','c']
def fun1():
# global list1
list1[0]='f' #這裡已經使用過全域性變量了,在函式內就不能再定義同名的區域性變量了
print('fun1內,打算定義一個與全域性變數同名的區域性變數:')
"""
若這一行沒有註釋掉#global list1就不會報錯
緣由是在同一個作用域中被定義了全域性變數,此時是全域性變數被賦值,修改
"""
# list1=['s'] #這裡定義同名的變數,會報錯;
def fun2():
print('fun2內,打算定義一個與全域性變數同名的區域性變數:')
list1=[123,'abc'] #這裡定義了一個與全域性變數同名的區域性變數
list1.append('123') #這裡使用的也是區域性變數
print('fun2函式內:',list1)
fun1()
print('執行fun1之後,函式外:',list1)
fun2()
print('執行fun2之後,函式外:',list1)
參考Python細節之7、global與nonlocal的使用
之前也寫過,但不詳細global與nonlocal