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——只有"重新绑定名字"才需要。追问方向:globalnonlocal 的区别、闭包变量存储在 __closure__ cell 对象中、del 语句对作用域判定的影响。