Python 3.1 快速導覽 - 函數 範圍規則

函數 (function) 內的變數 (variable) 包括參數 (parameter) 都稱為區域變數 (local variable) ,這意思是說區域變數的使用範圍 (scope) 限於函數的區塊 (block) 內,一旦離開該區塊範圍,便無法繼續使用原本在區塊內的變數值。



下例示範變數的範圍規則
def outer(a):
    def inner(a):
        a += 1
        print("inner a =", a)
    
    a += 1
    inner(a)
    print("outer a =", a)

a = 12
print("global a =", a)
outer(a)
print("global a =", a)

# 《程式語言教學誌》的範例程式
# http://pydoing.blogspot.com/
# 檔名:scope01.py
# 功能:示範 Python 程式 
# 作者:張凱慶
# 時間:西元 2010 年 12 月 


執行結果如下



我們在 outer() 函數裡頭另外定義了 inner() 函數, inner() 就只能在 outer() 裡頭被呼叫 (call) 。第 10 行
a = 12


所有函數的最外圍建立變數 a ,屬於這個程式檔案的全域範圍。然後以 a 當成參數傳遞給 outer() ,這時程式執行進到 outer() 裡頭,第 6 行
a += 1


a 遞增 1 ,也就是說 outer() 的參數 a 加上 1 ,現在 outer() 的參數 a 等於 13 ,然後再以 a 當成參數傳遞給 inner() ,程式執行進入 inner() 裡頭,第 3 行
a += 1


inner() 的參數 a 加上 1 ,現在 inner() 的參數 a 等於 14 ,因此我們在印出的第二行看到 inner a = 14 。 inner() 執行完,程式回到 outer() 印出 a ,因此我們在印出的第三行看到 outer a = 13 。 outer() 結束,程式會到全域的執行部份,這時再次印出 a ,因此我們看到 global a = 12 。


變數名稱都是 a ,但此 a 非彼 a 。參數只是函數內拷貝的副本,因此不會影響到範圍外相同名稱的變數。


如果我們想要在函數區塊中使用範圍外的變數,可使用關鍵字 (keyword) 中的 globalnonlocal 宣告範圍外的變數名稱。


下例示範在 inner() 使用 global ,當 inner() 將 a 加上 1 之時,最外層全域的 a 也遞增 1
def outer(a):
    def inner():
        global a 
        a += 1
        print("inner a =", a)
    
    a += 1
    inner()
    print("outer a =", a)

a = 12
print("global a =", a)
outer(a)
print("global a =", a)

# 《程式語言教學誌》的範例程式
# http://pydoing.blogspot.com/
# 檔名:scope02.py
# 功能:示範 Python 程式 
# 作者:張凱慶
# 時間:西元 2010 年 12 月 


執行結果如下



下例示範在 inner() 使用 nonlocal ,這時 inner() 裡的 a 是上一層的 a ,也就是 outer() 的 a
def outer(a):
    def inner():
        nonlocal a 
        a += 1
        print("inner a =", a)
    
    a += 1
    inner()
    print("outer a =", a)

a = 12
print("global a =", a)
outer(a)
print("global a =", a)

# 《程式語言教學誌》的範例程式
# http://pydoing.blogspot.com/
# 檔名:scope03.py
# 功能:示範 Python 程式 
# 作者:張凱慶
# 時間:西元 2010 年 12 月 


執行結果如下



中英文術語對照
函數function
變數variable
參數parameter
區域變數local variable
範圍scope
區塊block
呼叫call
關鍵字keyword






1 則留言:

zeros 提到...

版主大大你好:

我練習了你網站上的有關 global 程式碼,有錯誤但跟網站上的程式碼一模一樣
顯示: NameError: name 'a' is not defined

反而是nonlocal顯示沒有問題,想請教版主,這 global 程式碼的用途是否有誤