天天看點

您不知道的Python中global、nonlocal哪些事兒

Python中全局變量、局部變量以及global、nonlocal關鍵字的用法

1.全局變量和局部變量

前言:

  • 全局變量是在整個py檔案中聲明,全局範圍内都可以通路;
  • 局部變量是在某個函數中聲明的,隻能在該函數中調用它,如果試圖在超出範圍的地方調用,程式就爆掉了
  • 如果在函數内部定義與某個全局變量一樣名稱的局部變量,就可能會導緻意外的效果,可能不是你期望的。是以不建議這樣使用,這樣會使得程式很不健全。

有 4 條法則,來區分一個變量是處于局部作用域還是全局作用域:

  1. 如果變量在全局作用域中使用(即在所用函數之外),它就總是全局變量。
  2. 如果在一個函數中,有針對該變量的 global 語句,它就是全局變量。
  3. 否則,如果該變量用于函數中的指派語句,它就是局部變量。
  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 語句。

  • 在一個函數中,一個變量要麼總是局部變量,要麼總是全局變量。函數中的代碼沒有辦法先使用名為 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之外的内置作用域中。

表示在局部作用域中,調用父級作用域中的變量;如果嵌套了很多層,最多隻能作用到最頂層的函數,不能作用于全局變量。

您不知道的Python中global、nonlocal哪些事兒
您不知道的Python中global、nonlocal哪些事兒

動手算算這些題,理論要和實際相結合

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的結果:

您不知道的Python中global、nonlocal哪些事兒

不加子產品A的結果:

您不知道的Python中global、nonlocal哪些事兒