Python中全局變量、局部變量以及global、nonlocal關鍵字的用法
1.全局變量和局部變量
前言:
- 全局變量是在整個py檔案中聲明,全局範圍内都可以通路;
- 局部變量是在某個函數中聲明的,隻能在該函數中調用它,如果試圖在超出範圍的地方調用,程式就爆掉了
- 如果在函數内部定義與某個全局變量一樣名稱的局部變量,就可能會導緻意外的效果,可能不是你期望的。是以不建議這樣使用,這樣會使得程式很不健全。
有 4 條法則,來區分一個變量是處于局部作用域還是全局作用域:
- 如果變量在全局作用域中使用(即在所用函數之外),它就總是全局變量。
- 如果在一個函數中,有針對該變量的 global 語句,它就是全局變量。
- 否則,如果該變量用于函數中的指派語句,它就是局部變量。
- 但是,如果該變量沒用用在指派語句中,它就是全局變量。
閱讀 例1,可以更好地了解這些法則,
# 例 1
def test1():
global str1
str1 = 'hello' # 這是全局變量
def test2():
str1 = 'python' # 這是局部變量
def test3():
print(str1) # 這是全局變量
str1 = 42 # 這是全局變量
test1()
print(str1) # out: hello
解釋:在 test1() 函數中,str1 是全局 str1 變量,因為在函數的開始處,有針對 str1 變量的 global 語句。在 test2() 函數中,str1 是局部變量,因為在該函數中有針對它的指派語句。在 test3() 函數中,str1 是全局變量,因為在這個函數中,既沒有指派語句,也沒有針對它的 global 語句。
- 在一個函數中,一個變量要麼總是局部變量,要麼總是全局變量。函數中的代碼沒有辦法先使用名為 str1 的局部變量,稍後又在同一個函數中使用全局變量。
- 如果想在一個函數中修改全局變量中存儲的值,就必須對該變量使用 global 語句。
- 在一個函數中,如果試圖在局部變量指派之前就使用它,Python就會報錯。如例2
#例 2
def test1():
print(str1) # ERROR
str1 = 'hello world' # 局部變量
str1 = 'hi' # 全局變量
test1()
'''
報錯:
File "E:/test/test.py", line 92, in test1
print(str1) # ERROR
UnboundLocalError: local variable 'str1' referenced before assignment
'''
例2解釋:之是以報錯,因為 Python 看到 test1() 函數中有針對 str1 的指派語句,是以會認為 str1 變量是局部變量。但是 print(str1) 語句的執行在 str1 指派之前,局部變量 str1 并不存在(即指派之前應用本地變量 str1)。Python不會退回使用全局 str1 變量。
2. global語句
使用 global 語句可以在一個函數内修改全局變量。如果在函數内的頂部有 " global str1 "這樣的代碼,它就告訴 Python ,“在這個函數中,str1 指的是全局變量,是以不要用這個名字建立一個局部變量”。例如下面代碼:
def test1():
global str1
str1 = 'one'
str1 = 'global'
test1()
print(str1) # out: one
因為 str1 在 test1() 的頂部被聲明 gloabl,是以當 str1 被指派為 ‘one’ 時,指派發生在全局作用域的 str1 上。沒有建立局部 str1 變量。
3. nonlocal語句
Python 3.0 引入了一條新的nonlocal語句,實際上,當執行到 nonlocal 語句的時候,nonlocal中列出的名稱必須在一個嵌套的def中提前定義過,否則,将會産生一個錯誤。nonlocal名稱隻能出現在嵌套的def中,而不能在子產品的全局作用域中或def之外的内置作用域中。
表示在局部作用域中,調用父級作用域中的變量;如果嵌套了很多層,最多隻能作用到最頂層的函數,不能作用于全局變量。

動手算算這些題,理論要和實際相結合
a = 1
def func_1():
a =2
def func_2():
# a = 3 #子產品A
def func_3():
nonlocal a
a = 4
print(' 8行:',a)
print(' 9行:',a)
func_3()
print('11行:',a)#2 --> 4
print('12行:',a)
func_2()
print('14行:',a)#2-->4
print('15行:',a)
func_1()
print('17行:',a)#全局變量,nonlocal無權更改
上面代碼中,加上子產品A的結果:
不加子產品A的結果: