作用域指变量 / 函数的 “有效访问范围”,Python 按 “就近原则” 查找变量,核心分为 4 类,关键规则用 “查找顺序” 和 “修改权限” 两点讲透:
一、4 类基本作用域(LEGB 查找顺序)
Python 访问变量时,会按以下顺序逐层查找,找到即停止,找不到则报错:
- L(Local,局部作用域):函数 / 方法内部定义的变量(如函数内用
a = 1
定义的变量),仅在当前函数内有效。 - E(Enclosing,嵌套作用域):外层嵌套函数的作用域(如函数 A 里嵌套了函数 B,B 可访问 A 内定义的变量)。
- G(Global,全局作用域):单个
.py
文件内、所有函数 / 类之外定义的变量(如文件最顶部写a = 1
),整个文件内的函数 / 类可访问。 - B(Built-in,内置作用域):Python 自带的内置函数 / 变量(如
print()
、len()
、True
),无需定义可直接用。
二、核心规则:“读” 和 “改” 的权限差异
这是最容易踩坑的点,关键看变量是 “读取值” 还是 “修改值”:
1. 读取变量:默认按 LEGB 顺序查找,无需额外声明
- 局部作用域可直接读嵌套 / 全局 / 内置变量(只要外层有定义)。
global_a = 10 # 全局变量 def func():print(global_a) # 读全局变量,无需声明,输出 10 func()
2. 修改变量:必须用关键字声明 “要修改的是外层作用域变量”
-
修改全局变量(Global):函数内要给全局变量赋值(如
global_a = 20
),必须先写global 变量名
声明,否则会被当成 “局部变量”。global_a = 10 def func():global global_a # 声明“要修改全局变量”global_a = 20 # 真正修改全局变量 func() print(global_a) # 输出 20
-
修改嵌套作用域变量(Enclosing):Python 3 用
nonlocal 变量名
声明(Python 2 无此关键字),作用是 “修改外层嵌套函数的变量”,而非创建局部变量。def outer():enclosing_a = 10def inner():nonlocal enclosing_a # 声明“要修改嵌套变量”enclosing_a = 20inner()print(enclosing_a) # 输出 20(嵌套变量被修改) outer()
-
局部变量(Local):直接赋值即可,无需声明(如
local_a = 5
),仅在当前函数内有效。
三、常见误区总结
-
误区:“同一文件内的全局变量,函数里直接赋值就能改”
错!不写global
时,函数内的变量名 = 值
会创建 “局部变量”,和外层全局变量同名但无关,相当于 “新变量覆盖了外层变量的访问”。 -
误区:“只有跨文件才需要 global”
错!global
作用是 “告诉 Python:我要改的是当前文件的全局变量”,和是否跨文件无关,仅和 “是否在函数内修改全局变量” 有关。