深入理解 Python 中的 global 與 nonlocal 關鍵字
更新日期: 2024 年 11 月 18 日
本文為 python 作用域系列文,第二篇:
- 基礎:深入理解 Python 的作用域與 LEGB 原則
- 1 階進化:深入理解 Python 中的 global 與 nonlocal 關鍵字
- 2 階進化:深入理解 Python 中的閉包(Closure)
在學習 Python 的過程中,變數的作用域是一個重要的概念。
理解如何在不同的作用域中訪問和修改變數,對於寫出高品質的代碼至關重要。
Python 提供了兩個關鍵字——global
和 nonlocal
,用於在函式中明確地聲明變數的作用域。
本文將為新手詳細介紹這兩個關鍵字的用法和注意事項。
什麼是作用域?
作用域(Scope)是指變數在程式中的可見範圍。Python 中的作用域主要分為四種,遵循 LEGB(Local、Enclosing、Global、Built-in) 原則:
- Local(本地作用域):函式內部定義的變數。
- Enclosing(嵌套作用域):嵌套函式的外部函式作用域。
- Global(全域作用域):模組級別,即整個程式範圍內的變數。
- Built-in(內建作用域):Python 內建的變數和函式,如
len()
。
global
關鍵字
用途
global
關鍵字用於在函式內部聲明全域變數。
這意味著在函式內部,你可以對全域變數進行讀取和修改。
基本用法
x = 10 # 全域變數
def modify_global():
global x
x = 20 # 修改全域變數
print(f"函式內部的 x:{x}")
modify_global()
print(f"函式外部的 x:{x}")
# 輸出:
# 函式內部的 x:20
# 函式外部的 x:20
在這個例子中,我們在函式內部使用 global x
,從而可以修改全域變數 x
。
不使用 global
的情況
如果不使用 global
關鍵字,函式內部的同名變數會被視為本地變數,不會影響全域變數。
x = 10
def modify_local():
x = 20 # 本地變數
print(f"函式內部的 x:{x}")
modify_local()
print(f"函式外部的 x:{x}")
# 輸出:
# 函式內部的 x:20
# 函式外部的 x:10
nonlocal
關鍵字
用途
nonlocal
關鍵字用於在嵌套函式中聲明非本地且非全域的變數。
這通常用於修改外部函式(但不是全域作用域)中的變數。
基本用法
def outer_function():
x = 10 # 外部函式的變數
def inner_function():
nonlocal x
x = 20 # 修改外部函式的變數
print(f"內部函式的 x:{x}")
inner_function()
print(f"外部函式的 x:{x}")
outer_function()
# 輸出:
# 內部函式的 x:20
# 外部函式的 x:20
在這個例子中,inner_function
中的 nonlocal x
表示我們要修改外部函式 outer_function
中的變數 x
。
不使用 nonlocal
的情況
如果不使用 nonlocal
關鍵字,內部函式的同名變數會被視為本地變數,不會影響外部函式的變數。
def outer_function():
x = 10
def inner_function():
x = 20 # 本地變數
print(f"內部函式的 x:{x}")
inner_function()
print(f"外部函式的 x:{x}")
outer_function()
# 輸出:
# 內部函式的 x:20
# 外部函式的 x:10
global
與 nonlocal
的區別
- 作用範圍不同:
global
用於全域作用域,允許在函式內部修改全域變數。nonlocal
用於嵌套函式,允許內部函式修改外部函式的變數。
- 使用場景不同:
global
適用於需要在函式內部修改全域變數的情況。nonlocal
適用於需要在嵌套函式中修改外部函式變數的情況。
注意事項
謹慎使用全域變數
過多使用全域變數可能導致代碼難以維護和除錯。
應盡量使用參數傳遞和返回值來避免不必要的全域變數。
nonlocal
的限制
nonlocal
不能用於修改全域變數或本地變數,只能修改嵌套作用域中的變數。
x = 10
def outer_function():
def inner_function():
nonlocal x # 會引發錯誤,因為 x 不在嵌套作用域中
x = 20
inner_function()
outer_function()
# 輸出:
# SyntaxError: no binding for nonlocal 'x' found
避免命名衝突
在不同的作用域中使用相同的變數名可能導致混淆。建議使用清晰、具體的變數名。
實際應用
計數器函式
使用 nonlocal
創建一個簡單的計數器函式。
def counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
c = counter()
print(c()) # 輸出:1
print(c()) # 輸出:2
print(c()) # 輸出:3
配置全域設定
使用 global
來修改全域設定,例如日誌級別。
log_level = "INFO"
def set_log_level(level):
global log_level
log_level = level
def log(message):
print(f"[{log_level}] {message}")
set_log_level("DEBUG")
log("這是一條調試訊息")
# 輸出:
# [DEBUG] 這是一條調試訊息
結論
理解 global
和 nonlocal
關鍵字有助於更靈活地控制變數的作用域。
這對於編寫複雜的程式和構建更健壯的應用程式非常有用。
希望這篇文章能幫助你掌握這兩個關鍵字的用法,並在實際開發中加以應用。
進一步學習
- 閉包(Closure):深入理解函式如何捕獲外部變數。
- 裝飾器(Decorator):
nonlocal
在裝飾器中的應用。 - 命名空間(Namespace):更全面地理解變數的存儲和查找方式。