Python作为动态类型语言,变量的可访问范围由作用域规则决定,官方定义的LEGB模型是变量查找的核心依据,四个字母分别对应Local、Enclosing、Global、Built-in四个作用域层级,变量查找会严格按照这个顺序从内到外进行。

LEGB模型各层级含义
Local 局部作用域
局部作用域指的是函数内部定义的变量,仅在当前函数执行时有效,函数执行结束后变量会被销毁。比如下面示例中函数内部的x就是局部变量:
def func():
x = 10 # 局部作用域变量
print(x)
func() # 输出10
print(x) # 报错,x不在全局作用域中
Enclosing 外部嵌套作用域
外部嵌套作用域出现在嵌套函数中,指的是外层函数的作用域,内层函数可以访问外层函数的变量。如果内层函数和外层函数有同名变量,内层会优先使用自己的局部变量:
def outer():
y = 20 # 外部嵌套作用域变量
def inner():
print(y) # 访问外层函数的y
inner()
outer() # 输出20
Global 全局作用域
全局作用域指的是模块层级定义的变量,在整个模块的任意函数中都可以访问,但如果要在函数内部修改全局变量,需要使用global关键字声明:
z = 30 # 全局作用域变量
def func():
global z
z = 40 # 修改全局变量z
print(z)
func() # 输出40
print(z) # 输出40,全局变量已被修改
Built-in 内置作用域
内置作用域是Python解释器启动时加载的作用域,包含内置函数、内置异常等,比如print、len、int都属于内置作用域的内容,所有代码都可以直接调用:
# 内置函数属于内置作用域
print(len([1,2,3])) # 输出3,len是内置函数
print(int("100")) # 输出100,int是内置类型
LEGB模型的查找顺序验证
当代码中引用一个变量时,Python会按照Local -> Enclosing -> Global -> Built-in的顺序依次查找,找到第一个匹配的变量就停止查找,如果四个层级都没有找到就会抛出NameError异常。
# 四个层级都有同名变量的场景
name = "global_name" # 全局作用域
def outer():
name = "enclosing_name" # 外部嵌套作用域
def inner():
name = "local_name" # 局部作用域
print(name) # 优先使用局部作用域的变量
inner()
outer() # 输出local_name
如果把inner函数中的name定义删除,就会查找外层outer的name:
name = "global_name"
def outer():
name = "enclosing_name"
def inner():
# 没有定义局部name,查找外层enclosing作用域
print(name)
inner()
outer() # 输出enclosing_name
LEGB模型的实际应用注意事项
- 避免在局部作用域修改外层变量时忘记声明关键字,修改全局变量要用
global,修改外部嵌套作用域变量要用nonlocal - 不要滥用全局变量,全局变量会增加代码的耦合度,也容易引发变量被意外修改的问题
- 内置作用域的变量不要被自定义变量覆盖,比如不要定义名为
list、print的变量,否则会覆盖内置函数导致后续调用出错
闭包是LEGB模型的典型应用场景,内层函数可以捕获外层函数的变量状态,即使外层函数已经执行结束,内层函数依然可以访问这些变量:
def counter():
count = 0 # 外部嵌套作用域变量,被内层函数捕获
def increment():
nonlocal count # 声明修改外部嵌套作用域的count
count += 1
return count
return increment
c = counter()
print(c()) # 输出1
print(c()) # 输出2
print(c()) # 输出3
掌握LEGB模型后,开发者可以快速定位变量相关的报错,也能更合理地设计变量的作用范围,写出更健壮的Python代码。
PythonLEGB_modelvariable_scope作用域规则修改时间:2026-07-22 09:45:29