文檔地址:https://docs.python.org/zh-cn/3.6/tutorial/classes.html#python-scopes-and-namespaces
python中的變量查找順序是按照LEGB規則進行查找的,由內往外逐層查找,找到後就不再往後查找,
L:Local,局部作用域,函數內部的作用域
E:Enclosed,局部作用域與全局作用域之間的作用域,例如函數嵌套中的外層函數的作用域
G:Global,全局作用域,所有函數外部的作用域,與模塊同層級
B:Built in,內置變量的作用域
global用於聲明一個非全局變量為全局變量,全局變量在函數內部只可引用不能修改,如果修改也就是出現"="賦值運算,則相當於在函數內部新建了一個與全局變量同名的局部變量,此時引用必須在定義之後,否則會找不到改局部變量而報錯。
比如下面這段代碼:
a = 10
def fun1():
print(a)
a = 20
def fun2():
a = 20
print(a)
fun1()
fun2()
fun2正常,fun1報錯"UnboundLocalError: local variable ‘a’ referenced before assignment",原因是fun1和fun2中a=20相當於聲明了一個局部變量,而fun1中先引用後聲明所以才會出現上面的錯誤。
因為fun2中是新建的局部變量,所以說賦值操作不會影響全局變量a的值,a還是等於10,
a = 10
def fun2():
a = 20
fun2()
print(a)
10
如果需要fun2中引用的a是全局變量a,可以使用global關鍵字在函數內部聲明一下,
a = 10
def fun2():
global a
a = 20
print(a)
fun2()
print(a)
10
20
global關鍵字在函數內部聲明變量的時候,這個變量可以在全局作用域中未定義,此時相當於在函數內部新建了一個全局變量,
def fun():
global a
a = 20
fun()
print(a)
20
nonlocal關鍵字用於在局部作用域裡面引入Enclosed作用域裡面的變量(該作用域裡離自己最近的那個同名變量),被nonlocal修飾的變量要求在Enclosed作用域中必須存在,否則報錯。在局部作用域裡對經nonlocal修飾的變量進行修改刪除等操作,操作的都是外層Enclosed作用域中的變量。
下面是局部作用域中修改nonlocal修飾的變量,
def fun1():
a = 10
def fun2():
nonlocal a
a = 20
fun2()
print(a)
fun1()
20
nonlocal修飾的變量在Enclosed作用域之間必須存在,可以越級,系統會從Enclosed作用域中由內往外,引入離局部作用域最近的那個同名變量,
def fun1():
a = 10
def fun2():
def fun3():
nonlocal a
a = 20
fun3()
fun2()
print(a)
fun1()
20
如果變量a在Enclosed作用域中不存在,比如說把a調換到全局作用於當中,就會報錯,
a = 10
def fun1():
def fun2():
def fun3():
nonlocal a
a = 20
fun3()
fun2()
print(a)
fun1()
SyntaxError: no binding for nonlocal 'a' found