在学习函数时,我们经常会遇到一个经典问题:同名变量在函数内外是否互相影响? 这其实就涉及到 Python 中的"变量作用域(Variable Scope)"。 理解作用域是掌握函数运行机制的重要一步,它决定了变量的"可见性"和"生命周期"。
本节我们将详细讲解 局部变量与全局变量 的区别、作用范围,以及如何在函数中正确地使用它们。
一、变量的作用域(Scope)
作用域(Scope) 指的是变量在程序中可访问的范围。 在 Python 中,变量的作用域主要分为两类:
- 局部变量(Local Variable):在函数内部定义,只能在函数内部使用。
- 全局变量(Global Variable):在函数外部定义,可以在整个程序中使用。
二、局部变量
局部变量是在函数内部创建的变量,仅在函数执行期间有效。 当函数执行结束后,局部变量就会被销毁。
python
def show_message():
message = "Hello from function"
print(message)
show_message()
# print(message) # 报错:NameError: name 'message' is not defined
解析:
message是函数内部定义的变量;- 它在
show_message()内有效; - 函数执行完毕后,
message不再存在。
三、全局变量
全局变量是在函数外部定义的变量,可以被函数内部访问(但不能直接修改)。
python
name = "Tom"
def greet():
print(f"你好,{name}")
greet() # 你好,Tom
解析:
- 变量
name定义在函数外,是全局变量; - 函数内部可以直接读取它的值;
- 但如果在函数内试图重新赋值同名变量,会创建一个新的"局部变量"。
四、局部变量与全局变量同名时
当函数中出现与全局变量同名的变量时,Python 会优先使用函数内的局部变量。
python
x = 10
def test():
x = 5
print("函数内x =", x)
test()
print("函数外x =", x)
输出:
ini
函数内x = 5
函数外x = 10
结论: 局部变量会屏蔽同名的全局变量,仅在函数内生效。
五、如何在函数中修改全局变量
默认情况下,函数内不能直接修改全局变量的值。 如果希望在函数内部修改全局变量,必须使用 global 关键字声明。
python
count = 0
def add():
global count # 声明使用全局变量
count += 1
for _ in range(3):
add()
print("count =", count)
输出:
ini
count = 3
注意事项:
- 使用
global时要谨慎; - 全局变量修改过多,会让程序难以维护;
- 在大型项目中,推荐通过函数参数与返回值传递数据,而非频繁操作全局变量。
六、嵌套函数与 nonlocal 关键字
如果函数内部还有一个嵌套函数(函数中定义函数),那么还会出现 闭包变量(Enclosed Variable) 的情况。 此时可使用 nonlocal 关键字修改外层函数的变量。
python
def outer():
x = 10
def inner():
nonlocal x
x += 5
print("inner中x =", x)
inner()
print("outer中x =", x)
outer()
输出:
ini
inner中x = 15
outer中x = 15
解释:
nonlocal用于修改外层函数作用域中的变量;- 如果不用
nonlocal,则x += 5会新建一个局部变量,不影响外层x。
七、作用域规则:LEGB 原则
Python 的变量查找顺序遵循 LEGB 原则:
| 级别 | 全称 | 含义 |
|---|---|---|
| L | Local | 局部作用域(函数内部) |
| E | Enclosing | 外层函数的作用域(嵌套函数) |
| G | Global | 全局作用域(模块级) |
| B | Built-in | 内置作用域(Python自带函数) |
当访问变量时,Python 会按顺序从 L → E → G → B 查找,一旦找到就停止。
示例:
python
x = "Global"
def outer():
x = "Enclosing"
def inner():
x = "Local"
print(x)
inner()
outer()
输出:
sql
Local
因为 x 在局部作用域(L)中找到了,所以不会再继续往外层查找。
八、实战案例:计数器函数
我们用一个例子来综合演示局部变量、全局变量和 nonlocal 的用法。
python
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
c = make_counter()
print(c()) # 1
print(c()) # 2
print(c()) # 3
解析:
count是外层函数的局部变量;nonlocal让内部函数counter()修改它;make_counter()返回的函数形成了"闭包";- 每次调用
c()时,count都能保持状态。
九、总结
| 分类 | 定义位置 | 生效范围 | 生命周期 |
|---|---|---|---|
| 局部变量 | 函数内部 | 仅函数内有效 | 函数结束后销毁 |
| 全局变量 | 函数外部 | 整个程序有效 | 程序运行期间一直存在 |
| nonlocal 变量 | 外层函数作用域 | 内外层函数共享 | 外层函数存在期间 |
十、编程建议
- 优先使用局部变量,减少全局变量依赖;
- 避免同名变量混用,提高可读性;
- 仅在必要时使用 global 或 nonlocal;
- 通过参数与返回值传递数据,让函数更独立、更易测试。
结语: 掌握局部变量与全局变量,是理解 Python 函数运行机制的重要基础。 当你真正理解了作用域规则(LEGB),你就能写出更高质量、更安全的代码。