Skip to content

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. globalnonlocal关键字

如果在函数内部直接写 x = ...,Python 的默认逻辑是: 在当前局部作用域(L)内建立一个新的局部变量 x ,而不会去修改外面的变量。为了突破这个限制,需要 globalnonlocal来显式声明,告诉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. globalnonlocal 核心对比

维度globalnonlocal
目标作用域全局作用域 (Global)嵌套外层函数作用域 (Enclosing)
适用上下文任意函数体内部仅限嵌套函数(Nested Function)内部
变量未定义时的行为赋值时会自动在全局新建变量直接抛出SyntaxError 语法错误
同作用域互斥性同一变量不可与nonlocal 重复声明同一变量不可与global 重复声明

5. 常见语法错误

  1. 声明同时赋值global x = 10 导致的 SyntaxError
  2. 未声明即修改:在局部作用域执行 x += 1(无 global/nonlocal)导致的 UnboundLocalError