Python 变量作用域详解(Python 3.x)
变量作用域是指变量可被访问的代码范围。与 Java 等语言不同,Python 的变量作用域规则更灵活,尤其在全局变量和局部变量的区分上有特殊机制。本文将详细解析 Python 中变量的作用域类型、访问规则及修改全局变量的方法。
作用域的基本类型
Python 中变量的作用域分为以下四种,按访问优先级从高到低排列:
- 局部作用域(Local):在函数内部定义的变量,仅在函数内有效。
- 嵌套作用域(Enclosing):在嵌套函数外层的函数中定义的变量(适用于闭包场景)。
- 全局作用域(Global):在模块(.py 文件)顶层定义的变量,整个模块内可访问。
- 内置作用域(Built-in):Python 内置的变量或函数(如
print
、len
)。
局部变量(Local)
在函数内部定义的变量默认为局部变量,仅在函数执行期间存在,函数外部无法访问。
示例:局部变量的特性
1 | # 全局变量 x |
输出结果:
1 | 函数内初始 x(参数):50 |
结论:
- 函数参数(如
x_param
)也是局部变量。 - 函数内部定义的变量(如
x_local
)仅在函数内有效。 - 局部变量与全局变量同名时,函数内优先使用局部变量。
全局变量(Global)
在模块顶层定义的变量为全局变量,可在模块内的任何函数外访问。若要在函数内修改全局变量,需用 global
关键字声明。
访问全局变量(无需声明)
函数内可直接访问全局变量(无需 global
声明):
1 | # 全局变量 |
修改全局变量(需用 global
声明)
若在函数内直接修改全局变量,Python 会将其视为局部变量(创建新的局部变量),而非修改全局变量。如需修改,必须用 global
声明:
1 | # 全局变量 |
如果不声明 global
:
1 | count = 0 |
global
关键字的作用
- 告诉 Python:“该变量是全局变量,不要创建局部变量”。
global
声明必须放在变量使用之前。
1 | name = "Alice" |
嵌套作用域(Enclosing)
当函数嵌套时,内层函数可访问外层函数的变量(非全局),这种作用域称为嵌套作用域。若要修改外层函数的变量,需用 nonlocal
关键字(Python 3 新增)。
示例:嵌套函数与 nonlocal
1 | def outer(): |
输出结果:
1 | 内层函数:Hello from inner |
说明:
- 若不用
nonlocal
,内层函数的message
会被视为局部变量。 nonlocal
仅用于嵌套作用域,不可用于全局变量。
作用域查找规则:LEGB 原则
当访问一个变量时,Python 按以下顺序查找:
- L(Local):当前函数内部的局部变量。
- E(Enclosing):外层函数的变量(嵌套作用域)。
- G(Global):模块顶层的全局变量。
- B(Built-in):Python 内置的变量或函数。
若找不到变量,会抛出 NameError
。
示例:LEGB 原则演示
1 | # 全局变量(G) |
常见问题与最佳实践
避免滥用全局变量:
- 全局变量会增加函数间的耦合,降低代码可读性。
- 优先通过函数参数传递数据,而非依赖全局变量。
区分
global
和nonlocal
:global
:用于修改全局变量(模块顶层)。nonlocal
:用于修改嵌套作用域的变量(外层函数)。
局部变量遮蔽(Shadowing):
- 若局部变量与全局变量同名,局部变量会 “遮蔽” 全局变量(函数内优先使用局部)。
1
2
3
4
5
6x = 100
def shadow():
x = 200 # 局部变量,遮蔽全局 x
print(x) # 输出:200
shadow()
print(x) # 输出:100(全局 x 未变)
v1.3.10