Python局部变量与全局变量
中等3全局变量和局部变量:弄清你的“小盒子”属于谁
在编程中,变量就像一个个小盒子,用来存放数据——比如数字、文字、列表等。但这些盒子所在的位置决定了谁能使用它们。有些盒子放在家里的客厅里(全局变量),全家人都能看到和修改;有些盒子放在你的私人房间(局部变量),只有你自己才能碰,别人进不去。弄懂“全局”和“局部”的概念,能帮你避免很多莫名其妙的bug,比如“明明定义了变量,怎么函数里外面用不了?”或者“函数里改了变量,怎么外面没变?”这类问题。
下面我们就用生活里常见的情景,把这两种变量讲清楚。
1. 全局变量:放在客厅里的公共盒子
全局变量是在所有函数之外定义的变量。它属于整个程序,你在程序的任何地方(包括函数内部)都能读取它。就像家里客厅的电视,全家人随时都能打开看。
例子:学校公共黑板
假设你在一所小学读书,学校门口有一块大黑板,上面贴着每天的班级通知。任何同学、任何老师都能看到它、在上面写字。这块黑板就是一个“全局变量”。
# 全局变量:学校名称(全校都能看到)
school_name = "阳光小学"
def say_school():
# 在函数内部可以直接读取全局变量
print("我所在的学校是:", school_name)
say_school() # 输出:我所在的学校是: 阳光小学
# 在函数外部也能直接使用
print("全校都叫:", school_name) # 输出:全校都叫: 阳光小学
特点:
- 在函数外定义,整个程序都可见。
- 全局变量默认可以在函数内读取,但不能直接修改(除非用
global声明)。 - 适合存放一些“通用”的数据,比如游戏中的总分数、配置参数、用户名等。
2. 局部变量:放在自己房间里的私人盒子
局部变量是在函数内部定义的变量。它只在当前函数执行时存在,函数执行结束后,“小盒子”就被回收了。其他函数无法访问它,也看不到它。就像你房间里的玩具——只能在房间里玩,拿到客厅别人就不能随便拿走,甚至别人都不知道你有这个玩具。
例子:零花钱记账
你有一个存钱罐,里面存着零花钱。每次妈妈给你零花钱,你都会记在一个小本子上(局部变量)。这个小本子只有你打开房间才能看到,别人看不到。
def add_money(amount):
# 局部变量:当前拥有的零花钱(只在这个函数内有效)
pocket_money = 0 # 初始为0元
pocket_money = pocket_money + amount
print("这次你拿到了", amount, "元,现在总共有", pocket_money, "元")
add_money(10) # 输出:这次你拿到了 10 元,现在总共有 10 元
add_money(20) # 输出:这次你拿到了 20 元,现在总共有 20 元
# 下面这行代码会报错,因为 pocket_money 是局部变量,在函数外不存在
# print(pocket_money) # 取消注释会看到 NameError
注意: 每次调用 add_money 时,pocket_money 都会重新初始化为 0,然后加上金额。所以两次调用分别输出 10 和 20,并没有累加——因为局部变量在函数结束时就被“扔掉”了。
特点:
- 在函数内部定义,只能在该函数内使用。
- 函数结束时变量被销毁,每次调用函数都会重新创建。
- 不同函数中的同名局部变量互不干扰,就像你房间里的玩具和弟弟房间里的同款玩具是完全独立的。
3. 全局变量 vs 局部变量:名字冲突怎么办?
有时候,你可能会在函数内部使用一个和全局变量同名的局部变量。Python 是怎么区分的呢?
- 如果函数内部没有对变量赋值,只是读取,那么 Python 会先找局部变量,找不到就去全局变量找。
- 如果函数内部对变量进行了赋值(比如
count = 10),那么 Python 就会认为你创建了一个新的局部变量,而不会修改全局变量。
例子:考试分数统计
# 全局变量:全班平均分
avg_score = 80
def calculate_avg(new_scores):
# 这里 avg_score 是局部变量?还是全局?我们来看
avg_score = sum(new_scores) / len(new_scores) # 会对 avg_score 赋值!
print("函数内计算的平均分:", avg_score)
my_scores = [90, 85, 92]
calculate_avg(my_scores) # 输出:函数内计算的平均分: 89.0
print("全局平均分仍是:", avg_score) # 输出:全局平均分仍是: 80
你看!函数内部的 avg_score = ... 创建了一个新的局部变量,它悄悄地把全局变量“藏”起来了。全局变量 avg_score 一点都没变。
4. 新手最容易犯的错误:无意中“隐藏”全局变量
很多同学想当然地在函数里修改一个全局变量,结果发现外面没变。上面的考试例子就是一个坑。要解决这个问题,必须使用 global 关键字,明确告诉 Python:“我要修改的是那个公共盒子,不是创建一个新盒子。”
4.1 用 global 修改全局变量
# 全局变量:游戏中的总生命值
total_hp = 100
def take_damage(dmg):
global total_hp # 声明:我要用全局的 total_hp
total_hp = total_hp - dmg
print("受到伤害后,剩余生命值:", total_hp)
take_damage(30) # 输出:受到伤害后,剩余生命值: 70
print("总生命值现在:", total_hp) # 输出:总生命值现在: 70,确实被修改了
如果没有 global total_hp 这句话,total_hp = total_hp - dmg 就会创建局部变量 total_hp,而全局的那个不会变。
4.2 但注意:如果是列表、字典等可变对象,可以通过方法修改而不需要 global
比如全局变量是一个列表,在函数内使用 .append() 添加元素,不需要 global,因为这是在修改列表本身,而不是重新赋值。
# 全局变量:零食清单
snacks = ["薯片", "巧克力"]
def add_snack(new_snack):
# 这里没有用 global,但通过 append 改变了列表内容
snacks.append(new_snack)
add_snack("饼干")
print(snacks) # 输出:['薯片', '巧克力', '饼干']
这是很多同学会迷惑的地方:为什么有的修改要 global,有的不需要?规则很简单:如果你给变量重新赋值(比如 snacks = [1,2]),就需要 global;如果只是对变量所指的对象做“更改”操作(如 .append、.remove、修改字典的键值),就不需要。因为变量名本身没有变,变的是里面的内容。
5. 完整示例:用全局变量记录函数被调用的次数
下面是一个结合了局部变量和全局变量的实际例子:一个函数用来计算几个数的平均值,同时另一个全局变量记录这个函数被调用了多少次。
# 全局变量:记录函数调用次数
call_count = 0 # 初始为0次
def average(numbers):
# 声明要修改全局变量 call_count
global call_count
call_count = call_count + 1 # 每调用一次,次数加1
# 局部变量:计算平均值
total = sum(numbers) # 局部变量,求和
avg = total / len(numbers) # 局部变量,平均值
print("本次的平均值是:", avg)
# 测试
list1 = [90, 80, 70]
list2 = [100, 95, 90]
average(list1) # 输出:本次的平均值是: 80.0
average(list2) # 输出:本次的平均值是: 95.0
average([60, 70, 80]) # 输出:本次的平均值是: 70.0
print("函数一共被调用了", call_count, "次") # 输出:函数一共被调用了 3 次
这个例子展示了:
- 全局变量
call_count用来记录总的次数,所有函数调用都能共享这个计数。 - 局部变量
total和avg只在每个函数运行期间存在,互不影响。
6. 常见错误汇总(新手必看)
| 错误场景 | 错误代码(示意) | 结果 | 正确做法 |
|---|---|---|---|
| 在函数内直接给全局变量赋值 | count = count + 1 (无 global) | 报错:UnboundLocalError(局部变量引用前未定义) | 加上 global count |
| 以为函数内能自动修改全局变量 | count = 5 (无 global) | 创建局部变量,全局不变 | 用 global 声明 |
| 在函数内读取全局变量,然后还想修改它 | 先读后写,无 global | 也会报错,因为Python把整个函数内的变量都视为局部了 | 在最开头用 global 声明 |
| 不同函数间想共享变量但误用了局部变量 | 在每个函数里各自定义同名变量 | 数据无法共享 | 用全局变量或函数参数/返回值 |
7. 总结与相关指引
一句话总结:
- 全局变量:放在客厅,全家通用,要修改必须说“global”。
- 局部变量:放在卧室,只有自己能碰,用完后自动消失。
什么时候用全局?
- 需要在多个函数之间共享同一份数据时(如游戏的最高分、配置参数)。
- 避免滥用全局变量,因为程序大了之后,全局变量容易被意外修改,导致难以排查的bug。通常优先考虑用函数参数和返回值来传递数据。
相关知识点(继续学习):
- [函数参数与返回值] —— 通过传参和返回,能更安全地共享数据。
- [可变对象与不可变对象] —— 理解为什么列表不需要global而数字需要。
- [命名空间与作用域] —— 深层次理解Python如何查找变量。
- [闭包与nonlocal] —— 当函数嵌套函数时,会用到的非局部变量。
掌握了变量作用域,你就能更自信地写出清晰、不出错的代码了。快去试试上面例子中的代码,亲手看看全局和局部变量是怎么工作的吧!
例题精讲
在Python中,关于全局变量和局部变量的说法,哪一项是正确的?
请看以下Python代码: x = 10 def func(): x = 20 func() print(x) 运行后输出什么?
在Python中,如果在函数内部直接给一个与全局变量同名的变量赋值(没有使用global关键字),则函数会修改全局变量的值。
在函数内部可以读取全局变量的值,但若要修改全局变量的值,必须使用global关键字声明。
补全代码,使程序能正确修改全局变量a的值并输出10:
a = 5
def change():
___ a = 10
change()
print(a)