1. 程式人生 > >python3的local, global, nonlocal簡析

python3的local, global, nonlocal簡析

python3:變數作用域及global,nonlocal的用法

在Python程式中宣告、改變、查詢變數名時,都是在一個儲存變數名的名稱空間中進行中,此名稱空間亦稱為變數的作用域。python的作用域是靜態的,在程式碼中變數名被賦值的位置決定了該變數能被訪問的範圍。即Python變數的作用域由變數所在原始碼中的位置決定.
變數作用域之LENGB

L = Local     區域性作用域
E = Enclosing 巢狀作用域
N = nonlocal  只作用於巢狀作用域,而且只是作用在函式裡面
G = global    全域性作用域
B = Built-in  內建作用域

python引用變數的順序: 當前作用域區域性變數->外層作用域變數->當前模組中的全域性變數->python內建變數.

下面講分別舉例說明:
1. L = Local     區域性作用域
區域性變數包含在def定義的函式體內。在函式體內宣告的變數,預設都是區域性變數,除非有特別說明,如全域性變數的宣告要用關鍵字global.

def testlocal():
    x = 123 # x即為區域性變數
print(x)

以上程式碼執行就會報NameError, 因為x是個區域性變數,在函式外要print(x), 按照上面python引用變數的順序,是找不了x變數的,故為報錯. 

NameError: name 'x' is not defined

1.1 再舉一例:

x = 123
def testlocal():
    print(x)

testlocal()

以上程式碼執行結果為123, 因為按照上面python引用變數的順序,是找不到x變數的,故會向外層作用域找,就會找到x=123

1.2 如果將程式碼改為:

x = 123
def testlocal():
    print(x)
    x = 100

testlocal()

這時以上程式碼執行就會報錯. 

UnboundLocalError: local variable 'x' referenced before assignment

什麼原因?新手常會遇到這類問題, 因為按照python引用變數的順序,當print(x)時,就會先在函式體內查詢x,能找到,但在他的下一行,故為在宣告前被引用是不對的.  
 

2. G = global    全域性作用域
全域性作用域的變數怎麼用呢?
先看例項:

x = 123
def testGlobal():
    print(x)
    x = 100
    
testGlobal()

這就是上面1.2的例項,會報錯,如果將其為:

x = 123
def testGlobal():
    global x
    print(x)
    x = 100
    
testGlobal()

試試看,結果執行結果為123, 是不會報錯的,自已體會一下吧. 

3. nonlocal的用法
這個一般是用在閉包函式裡. 例項如下:

x = 123
def outer():
    x = 100
    def inter():
        x = 200
    inter()
    print(x)
    
func()

執行的結果為100, 那如果要求inter中對x的修改是有效的,必須加上關鍵字nonlocal

x = 123
def outer():
    x = 100
    def inter():
        nonlocal x
        x = 200
    inter()
    print(x)
    
func()

執行的結果為200, 符合預期.

4. 其它.
python變數的作用域只在作用域內有效,需要注意的是,在if-elif-else, for-in, while, try-except-finally這些關鍵字中並不會產生特定的作用域,如下:

#!/user/bin/python3
#-*- coding:utf-8 -*-

for i in range(10):
    i = i + 1
print(i)
>>>10

執行結果並不會報錯,會輸入i, 這裡的i就是一個全域性變數,這是python的一個特點,如果在C/java中這種寫法就會報錯,會報變數i會宣告.