CC++ & Algorithm

变量的作用域

困难1
语言版本:C++
概述:变量有“领地”概念,函数内定义的变量只能在函数内使用,函数外定义的变量函数内可以读取但不能随意修改。

变量的作用域:理解代码中的“领地”规则

想象一下你在学校里:每个班级都有自己的黑板,老师在黑板上写的“明天春游”只有这个班的学生能看到;而学校大门口的告示板上写的通知,全校师生都能看。变量的作用域就是这个道理——每个变量都有自己能“生效”的区域,在这个区域里它能被访问,跨出这个区域就看不到它了。

为什么要关心作用域?因为程序里变量很多,如果所有变量都能在任何地方修改,那代码就会乱成一锅粥,就像全校所有班级都写在同一块黑板上的话,你根本分不清哪个通知是哪个班的。作用域帮我们管理变量的“归属权”,避免命名冲突,让代码更有条理。


一、局部变量(班级黑板)

在函数内部定义的变量,叫做局部变量。它只属于这个函数,函数外面无法访问它。

def show():
    message = "函数内部的秘密"   # 局部变量
    print(message)

show()          # 输出:函数内部的秘密
print(message)  # 报错!name 'message' is not defined

为什么函数外不能访问?
因为局部变量在函数调用时才被创建,函数执行完毕后就自动销毁了。就像班级黑板上的内容,老师一擦掉,别人就看不到了。

生活中的例子:你每天有妈妈给的零花钱(比如5元),这个钱只能你自己花,你不能直接拿姐姐的零花钱。每个函数就像一个人,它有自己的局部零花钱。


二、全局变量(学校告示板)

在所有函数外面、在代码顶层定义的变量,叫做全局变量。它就像学校告示板上的内容,所有人都能看到。

1. 在函数内可以读取全局变量

函数内部可以读取(使用)全局变量的值,不需要特殊声明。

school_name = "阳光小学"         # 全局变量

def show_school():
    print("我所在的学校是:", school_name)

show_school()                    # 输出:我所在的学校是:阳光小学

2. 在函数内不能直接修改全局变量

如果尝试在函数内给一个全局变量赋值(用 =),Python 会认为你在创建一个新的局部变量,它和外面的全局变量名字相同但彼此无关。

count = 0                # 全局变量:记录全班人数

def add_one():
    count = 10           # 这其实定义了一个新的局部变量,不会影响全局变量
    print("函数内count:", count)

add_one()                # 输出:函数内count: 10
print("函数外count:", count)  # 输出:函数外count: 0 (全局变量没变)

生活中的例子:学校告示板上写着“今天大扫除”,你看到后自己嘀咕了一句“改成明天吧”,但告示板上的字并没有改变——你只是在自己心里改了。只有你拿着粉笔去告示板上改写,才是真的修改。


三、如何真正修改全局变量:global声明

如果确实需要在函数内部修改全局变量,必须用 global 关键字声明这个变量是全局的。

count = 0                    # 全局变量

def add_one():
    global count             # 声明count是全局变量
    count = count + 1        # 现在修改的是全局变量

add_one()
print(count)                 # 输出:1 (成功修改)

重要提醒global 声明一般只在需要修改全局变量时才用。能不用就尽量不用,因为滥用全局变量会让代码难以理解和调试。就像学校告示板,不是每个人都能上去改,只有校长或值日生才有权力。


四、新手最容易犯的错误

  1. 忘记 global 关键字
    以为函数内修改了全局变量,实际却创建了局部变量,导致程序逻辑错误。比如上面的 count 例子,如果不加 global,外面 count 还是0。

  2. 在函数内部意外重名
    函数内定义了一个与全局变量同名的变量,本意是想用全局变量,结果却变成了局部变量,覆盖了全局变量的访问能力。

    score = 90                    # 全局变量:考试分数
    
    def change():
        score = 100               # 想修改全局分数,但实际创建了局部变量
        print("函数内分数:", score)
    
    change()                      # 输出:函数内分数: 100
    print("函数外分数:", score)   # 输出:函数外分数: 90 (没改成功)
    
  3. 在函数内使用全局变量名但未赋值
    如果函数内只读取全局变量,不会产生问题;但如果既读取又赋值,Python 就会困惑——它会认为这个变量是局部的,但在赋值前你又读取了它,导致“变量未定义”错误。

    x = 10
    
    def test():
        print(x)         # 这里想读取全局x
        x = 20           # 但又写了一个局部x,导致冲突
    # 运行会报错:UnboundLocalError: local variable 'x' referenced before assignment
    

    解决方法:要么全用全局(加 global),要么不要这样混用。


五、作用域查找规则(LEGB)

Python 在访问一个变量时,按照以下顺序依次查找:

  • Local(本地) → 当前函数内部定义的变量
  • Enclosing(嵌套) → 外层函数(如果有嵌套函数)中定义的变量
  • Global(全局) → 整个程序顶层定义的变量
  • Built-in(内置) → Python 自带的函数和常量(比如 printlenTrue

简单记住:先找自己,再找外层,再找全局,最后找内置。一旦找到就停止查找。

举个例子(如果你还没学嵌套函数,可以跳过):

x = "全局x"           # 全局

def outer():
    x = "外层x"       # 嵌套作用域
    def inner():
        x = "内层x"   # 局部
        print(x)
    inner()

outer()               # 输出:内层x

如果 inner 函数里没有定义 x,就会去外层找,再找不到就去全局,最后去内置。


六、完整可运行示例:统计考试平均分

下面是一个综合例子,用全局变量记录总人数和总分,局部变量处理每一轮的输入,用函数来更新成绩。

total_students = 0       # 全局变量:学生总人数
total_score = 0          # 全局变量:总分数

def add_score(score):    # 参数score是局部变量
    global total_students, total_score   # 声明要修改全局变量
    total_students = total_students + 1  # 人数加1
    total_score = total_score + score    # 总分加上新分数
    print("已录入分数:", score, ",当前总人数:", total_students)

# 主程序
print("请输入3个同学的考试成绩(按回车分隔):")
for i in range(3):
    s = int(input())           # 局部变量 s,存放本次输入
    add_score(s)               # 调用函数

average = total_score / total_students  # 计算平均分(全局变量)
print("班级平均分:", average)

运行示例(假设输入 85, 92, 78):

请输入3个同学的考试成绩(按回车分隔):
85
92
78
已录入分数: 85 ,当前总人数: 1
已录入分数: 92 ,当前总人数: 2
已录入分数: 78 ,当前总人数: 3
班级平均分: 85.0

这个例子中,全局变量 total_studentstotal_score 记录整个班级的数据,函数 add_score 负责更新它们,而主程序中的 s 只是局部变量,函数执行完就消失了。


七、相关指引

掌握了变量的作用域,你就理解了函数内部和外部如何安全地交换数据。接下来可以学习:

  • 函数的参数与返回值——这是让函数和外界交流更灵活的方式(通常比全局变量更推荐)。
  • 递归函数——递归中的每一层调用都有自己的局部变量,理解作用域能帮你写出正确的递归。
  • 模块与命名空间——当程序变大,分成多个文件时,每个文件有自己的全局作用域,用 import 来访问。
  • nonlocal 关键字——用于嵌套函数中修改外层函数的局部变量。

记住:变量作用域就像学校的领地划分——班级内的事自己管,学校的事大家管,不要随便越界,但需要时可以通过规则(global)来协调。 这样你的代码就会井井有条。

例题精讲

1单选题

在Python中,以下关于变量作用域的说法,错误的是?

A在函数内部定义的变量是局部变量,只能在函数内部访问
B在函数外部定义的变量是全局变量,函数内部可以读取但无法直接修改
C使用global关键字可以在函数内部修改全局变量
D函数内部的局部变量与全局变量同名时,函数内部会优先使用全局变量
2单选题

执行以下代码后,输出的结果是? x = 10 def change(): x = 5 change() print(x)

A5
B10
C报错(NameError)
D15
3判断题

在Python中,函数内部可以任意读取函数外部定义的全局变量的值,但无法直接修改全局变量的值(除非使用global关键字)。

4填空题
以下代码使用嵌套函数,函数outer中定义了变量x,函数inner中试图修改外层的x。请填写正确的内容,使得最终输出为10。

def outer():
    x = 5
    def inner():
        ___  # 此处填写声明语句
        x = 10
    inner()
    print(x)
outer()
5填空题
以下代码中,函数func试图修改全局变量a,但未使用关键字,请填写正确的声明语句使得最终输出为20。

a = 10
def func():
    ___  # 此处填写声明语句
    a = 20
func()
print(a)