Python 作用域查找顺序 LEGB 详解

Python变量作用域查找顺序是LEGB:Local→Enclosing→Global→Built-in。Local指函数内定义的局部变量;Enclosing指嵌套函数中外层函数的局部变量;Global指模块级全局变量;Built-in指Python内置函数与常量。

Python 中变量的作用域查找顺序是 LEGB,即 Local → Enclosing → Global → Built-in。这个规则决定了当代码中使用一个变量时,Python 会按什么顺序去搜索它的定义。

Local(局部作用域)

函数内部定义的变量属于局部作用域,只在该函数内有效。每次调用函数都会创建新的局部作用域,函数执行完后自动销毁。

例如:

def func():
    x = 10        # x 是局部变量
    print(x)      # ✅ 可以访问
func()
print(x)          # ❌ NameError: name 'x' is not defined

Enclosing(嵌套作用域)

当一个函数内部定义了另一个函数(闭包),外层函数的局部变量对内层函数来说就是嵌套作用域中的变量。它不是全局的,也不是内层函数自己的局部变量,而是“被包围”的那一层。

注意:内层函数可以读取外层函数的变量,但默认不能直接赋值修改(需用 nonlocal 声明)。

例如:

def outer():
    y = "outer"
    def inner():
        print(y)   # ✅ 可以读取 enclosing 层的 y
    inner()
ou

ter()

Global(全局作用域)

模块顶层(不在任何函数或类中)定义的变量属于全局作用域,在整个模块内都可访问(除非被局部同名变量遮蔽)。在函数中读取全局变量无需声明,但要修改必须用 global 关键字。

  • 读取全局变量:直接使用变量名即可
  • 修改全局变量:需在函数开头写 global var_name
  • 多个全局变量可一次声明:global a, b, c

Built-in(内置作用域)

Python 预定义的函数和常量,比如 len()print()TrueNone 等,都位于内置作用域。它是作用域链的最外层,只有当前面三层都找不到变量时,才会查这里。

⚠️ 注意:不要轻易覆盖内置名称,否则可能导致意外行为。

len = "my string"   # 覆盖了内置 len()
print(len([1,2,3])) # ❌ TypeError: 'str' object is not callable

LEGB 是逐层向上查找的单向过程,一旦找到就停止,不会继续往更外层找。理解它有助于避免命名冲突、正确使用 global/nonlocal,也能更快定位变量未定义或值异常的问题。