Appearance
Python 变量作用域
1. 变量作用域与 LEGB 规则
1.1 作用域定义
变量作用域(Scope)决定了程序中变量的可见性与生命周期。Python 中的作用域分为四种类型:
- L (Local):局部作用域,即函数内部定义的变量。
- E (Enclosing):嵌套函数的外层函数作用域。
- G (Global):模块顶层的全局作用域。
- B (Built-in):Python 内置作用域。
1.2 LEGB 查找顺序
当程序读取变量时,解释器严格按照 L -> E -> G -> B 的顺序由内向外依次检索:
- 检索止于首次找到同名变量的位置。
- 若搜索至
Built-in仍未找到,则抛出NameError。
仅进行读取操作时,无需任何关键字显式声明作用域。
1.3 LEGB 程序示例
文件组织:
python-scope-demo/
├── module_a.py # 被导入模块(用于验证全局变量模块隔离与属性读取 module_a.z)
└── main.py # 核心主程序(包含 LEGB 读取穿透、nonlocal 跨层修改、global 验证)# module_a.py
z = "variable_in_module.py "Python
# main.py
y = "y(in main.py)"
def outer():
x = "x(in outer) "
def middle():
def inner():
print(x) # 1. 成功:跨越 middle,在 outer 中找到 (跨层 E)
print(y) # 2. 成功:直接找到模块顶层的全局变量 (到达 G)
print(z) # 3. 失败:L->E->G->B 找遍了都没有,抛出 NameError
inner()
middle()
outer()输出:
>>> %Run main.py
x(in outer)
y(in main.py)
Traceback (most recent call last):
File "C:\Users\Arin\Desktop\deimo\main.py", line 16, in <module>
outer()
File "C:\Users\Arin\Desktop\deimo\main.py", line 13, in outer
middle()
File "C:\Users\Arin\Desktop\deimo\main.py", line 12, in middle
inner()
File "C:\Users\Arin\Desktop\deimo\main.py", line 11, in inner
print(z)
NameError: name 'z' is not defined可以看到,最内层的inner()函数可以找到outer()的变量x,也可以找到全局变量y,但是无法找到另外模块的z。
2. global 和nonlocal关键字
如果在函数内部直接写
x = ...,Python 的默认逻辑是: 在当前局部作用域(L)内建立一个新的局部变量x,而不会去修改外面的变量。为了突破这个限制,需要global和nonlocal来显式声明,告诉Python这个变量是全局或者外层函数的。
2.1 作用机制
global 用于在局部作用域内声明变量绑定至模块级全局作用域(Global Scope),允许在函数内部对全局变量执行重新赋值操作。
2.2 语法约束与行为
- 语法规范:必须先声明后赋值,不支持声明同时赋值(如
global x = 1为语法错误)。 - 隐式创建:若全局作用域中不存在该变量,在函数内部声明
global并赋值后,将在全局作用域中新建该变量。
3. nonlocal 关键字原理与机制
3.1 作用机制
nonlocal 用于在嵌套函数内部声明变量绑定至外层非全局函数作用域(Enclosing Scope),允许修改外层函数的局部变量。
3.2 查找与绑定规则
- 搜索路径:从当前函数的直接上一层函数开始,逐层向更外层的嵌套函数搜寻,直至找到最近的同名局部变量。
- 作用域边界:搜寻仅限于函数作用域链,绝对不会穿透至全局作用域(Global Scope)。
- 绑定约束:若所有外层函数均未定义该变量,语法解析阶段将抛出
SyntaxError: no binding for nonlocal found。
4. global 与 nonlocal 核心对比
| 维度 | global | nonlocal |
|---|---|---|
| 目标作用域 | 全局作用域 (Global) | 嵌套外层函数作用域 (Enclosing) |
| 适用上下文 | 任意函数体内部 | 仅限嵌套函数(Nested Function)内部 |
| 变量未定义时的行为 | 赋值时会自动在全局新建变量 | 直接抛出SyntaxError 语法错误 |
| 同作用域互斥性 | 同一变量不可与nonlocal 重复声明 | 同一变量不可与global 重复声明 |
5. 常见语法错误
- 声明同时赋值:
global x = 10导致的SyntaxError。 - 未声明即修改:在局部作用域执行
x += 1(无global/nonlocal)导致的UnboundLocalError。