CC++ & Algorithm

Python局部变量与全局变量

中等3
语言版本:C++Python
概述:变量就像小盒子,全局变量是大家都能用的公共盒子,局部变量是只有某个函数才能用的私人盒子。

全局变量和局部变量:弄清你的“小盒子”属于谁

在编程中,变量就像一个个小盒子,用来存放数据——比如数字、文字、列表等。但这些盒子所在的位置决定了谁能使用它们。有些盒子放在家里的客厅里(全局变量),全家人都能看到和修改;有些盒子放在你的私人房间(局部变量),只有你自己才能碰,别人进不去。弄懂“全局”和“局部”的概念,能帮你避免很多莫名其妙的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 用来记录总的次数,所有函数调用都能共享这个计数。
  • 局部变量 totalavg 只在每个函数运行期间存在,互不影响。

6. 常见错误汇总(新手必看)

错误场景错误代码(示意)结果正确做法
在函数内直接给全局变量赋值count = count + 1 (无 global)报错:UnboundLocalError(局部变量引用前未定义)加上 global count
以为函数内能自动修改全局变量count = 5 (无 global)创建局部变量,全局不变global 声明
在函数内读取全局变量,然后还想修改它先读后写,无 global也会报错,因为Python把整个函数内的变量都视为局部了在最开头用 global 声明
不同函数间想共享变量但误用了局部变量在每个函数里各自定义同名变量数据无法共享用全局变量或函数参数/返回值

7. 总结与相关指引

一句话总结:

  • 全局变量:放在客厅,全家通用,要修改必须说“global”。
  • 局部变量:放在卧室,只有自己能碰,用完后自动消失。

什么时候用全局?

  • 需要在多个函数之间共享同一份数据时(如游戏的最高分、配置参数)。
  • 避免滥用全局变量,因为程序大了之后,全局变量容易被意外修改,导致难以排查的bug。通常优先考虑用函数参数和返回值来传递数据。

相关知识点(继续学习):

  • [函数参数与返回值] —— 通过传参和返回,能更安全地共享数据。
  • [可变对象与不可变对象] —— 理解为什么列表不需要global而数字需要。
  • [命名空间与作用域] —— 深层次理解Python如何查找变量。
  • [闭包与nonlocal] —— 当函数嵌套函数时,会用到的非局部变量。

掌握了变量作用域,你就能更自信地写出清晰、不出错的代码了。快去试试上面例子中的代码,亲手看看全局和局部变量是怎么工作的吧!

例题精讲

1单选题

在Python中,关于全局变量和局部变量的说法,哪一项是正确的?

A在函数内定义的变量默认是全局变量
B在函数外定义的变量在函数内无法访问
C在函数内使用global关键字可以修改全局变量
D局部变量只能在定义它的函数外使用
2单选题

请看以下Python代码: x = 10 def func(): x = 20 func() print(x) 运行后输出什么?

A10
B20
C报错(NameError)
D30
3判断题

在Python中,如果在函数内部直接给一个与全局变量同名的变量赋值(没有使用global关键字),则函数会修改全局变量的值。

4判断题

在函数内部可以读取全局变量的值,但若要修改全局变量的值,必须使用global关键字声明。

5填空题
补全代码,使程序能正确修改全局变量a的值并输出10:

a = 5
def change():
    ___ a = 10
change()
print(a)