Python编译函数时,只要变量出现在赋值语句左侧(如x += 1),就立即将其标记为局部变量,导致后续读取时报UnboundLocalError;global/nonlocal必须在函数顶部声明,且nonlocal不能用于全局变量。

因为Python在编译函数时,只要看到变量出现在赋值语句左侧(比如 x += 1、x = 5),就**立刻把它标记为局部变量**——哪怕赋值语句在 if False: 里,哪怕它只在函数末尾出现。之后所有对该变量的读取(包括 += 左侧的读取),都会去局部作用域找,而此时它还没被赋值,于是报 UnboundLocalError。
为什么 x += 1 会触发这个错误
这行代码等价于 x = x + 1:先读取 x,再计算,最后赋值。Python 编译器看到 =,就把 x 判定为局部变量;但执行时,它又需要读取这个“局部变量 x”的当前值——而局部作用域里根本没这个变量,所以崩了。
-
x += 1、x -= 1、x *= 2都属于复合赋值,全部触发相同机制 - 即使全局有同名变量,也完全不影响编译期判定
- 错误位置常在“读取行”,但根因永远在后面某处的赋值语句
global 声明必须写在函数顶部,不能藏在 if 里
global 不是运行时补救,而是编译期指令。Python 要在扫描函数体第一遍时就知道“这个变量我打算操作全局的”,否则照样按默认规则走。
- ✅ 正确:
def f(): global x; print(x); x += 1 - ❌ 错误:
def f(): if True: global x; print(x)→ 语法错误,global必须在函数最外层作用域声明 - ❌ 错误:
def f(): if cond: global x; x = 1→ 编译器忽略分支里的global,仍判x为局部
nonlocal 不能跨层,也不能指向全局变量
如果外层是嵌套函数(非模块级),想改外层函数的变量,必须用 nonlocal;但它只认直接外层,且要求那个变量**已经存在**。
立即学习“Python免费学习笔记(深入)”;
- 外层是模块级变量 → 只能用
global,用nonlocal报SyntaxError - 外层是
def outer(): x = 1; def inner(): ...→inner里改x必须nonlocal x - 多层嵌套要改最外层?得链式写:
nonlocal x(改中间层),中间层再用nonlocal x(改最外层)
最容易被忽略的是:这个错误不是“变量没定义”,而是“Python提前锁死了作用域”。你不能靠运行时逻辑绕过编译规则——要么提前声明 global/nonlocal,要么重命名避免冲突,要么把值当参数传入、返回新值。任何试图在分支里动态决定是否声明的做法,都注定失败。


















