前言:
有 4 條法則,來區分一個變量是處於局部作用域還是全局作用域:
閱讀 例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 語句。
#例 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 變量。
使用 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 變量。
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的結果: