LEGB 是 Python 的名称查找顺序:Local(函数内局部)→ Enclosing(外层嵌套函数)→ Global(模块全局)→ Builtins(内置),由内向外找到第一个绑定即停。
x = "global"
def outer():
x = "enclosing"
def inner():
x = "local"
print(x) # local,就近原则
作用域判定在编译期完成:函数体内只要有对某名字的赋值语句,该名字在整个函数内就是局部变量。经典坑:
def f():
print(x) # UnboundLocalError!下面有赋值,x 被当作局部变量
x = 1
闭包中修改外层变量:直接赋值会被解释为新建局部变量,必须用 nonlocal 声明引用外层(非全局)作用域的绑定;修改模块级变量用 global。
def counter():
n = 0
def inc():
nonlocal n # 关键:声明后才能改外层变量
n += 1
return n
return inc
补充:闭包捕获的是变量本身而非值快照,循环中创建闭包要用默认参数固定值。若只是改对象内容(lst.append)不需要 nonlocal——只有"重新绑定名字"才需要。追问方向:global 与 nonlocal 的区别、闭包变量存储在 __closure__ cell 对象中、del 语句对作用域判定的影响。