def x():
b = 12
def y():
global a, b
a = 1
b = 2
y()
print("b =", b) # 輸出 12?
x()
print(a) # 1
print(b) # 2
為什麼 x() 內部打印 b=12,而全局 b 卻變成了 2?這揭示了 Python 作用域機制的核心規則。
global 不創建變量,只聲明「後續對該名字的操作映射到模塊級命名空間」
global a, b 告訴解釋器:函數內對 a、b 的賦值/讀取,直接操作模塊全局作用域Python 變量查找順序:Local(局部)→ Enclosing(嵌套/閉包)→ Global(全局/模塊)→ Built-in(內置)
=、+= 等)默認創建/修改 局部變量global 強制跳過 L、E,直接操作 Gnonlocal(Python 3)強制操作 E 層def x():
a = 1
def y():
print(a) # UnboundLocalError!
a = 2
y()
原因:編譯器掃描到 a = 2,判定 a 為局部變量。執行到 print(a) 時,局部 a 尚未賦值 → UnboundLocalError(而非 NameError)。
def x():
a = 12
def y():
print(a) # 正常輸出 12
y()
def x():
lst = ["in"]
def y():
lst[:] = ["out"] # 切片賦值,修改對象內容而非重新綁定
print(lst[0])
y()
print(lst[0]) # "out"
關鍵:lst[:] = ... 修改列表內容;lst = ... 會創建新局部變量。
def x():
a, b = 1, 2
def y(a=a, b=b): # 默認值在定義時捕獲
a, b = 3, 4
return a, b
a, b = y()
print(a, b) # 3 4
注意:默認值避免使用可變對象(列表、字典),否則會共享同一對象導致難以排查的 Bug。
MAX_SIZE = 100)self.attr 替代全局/閉包變量global x: int 增加可讀性(Py 3.8+)理解 Python 作用域機制,是從「能跑通」進階到「寫出健壯、可維護代碼」的關鍵一步。下次遇到 UnboundLocalError,請檢查是否在賦值前引用了同名局部變量。