第1章 1.3 变量、声明与作用域

上 一章我们折腾了半天开发者工具,终于能看懂浏览器在背后偷偷摸摸搞的那些事儿了——控制台打印、Network 抓包、Elements 审查,这些工具就像是给你的代码装了一双透视眼。但光会看还不够,咱们得学会「存放数据」,不然程序运行完啥都没留下,那跟看完电影就忘剧情有啥区别?

这一章我们要解决一个问题:怎么让电脑记住你的数据,并且想用的时候能随时调用? 学完之后,你就能写出真正「有记忆」的程序了。


🎯 开场 3 分钟:为什么要学这个?

场景引入

想象你去超市买东西。进门推了个购物车(变量),你往里面放了一瓶牛奶(数据),然后继续逛。如果不问收银台牛奶多少钱,你怎么知道车里放的是牛奶还是可乐?

程序也一样——你得先「声明」一个变量,告诉电脑「我要存东西了」,然后往里面放数据,之后才能取出来用。

痛点问题

你是不是遇到过这种情况:

  • ❌ 写了个计算器,输入 a + b,结果出来个莫名其妙的数字
  • ❌ 想修改变量值,结果 Python 报 NameErro\n\n![Simple tech illustration expla](https://blog.xxyye.com/wp-content/uploads/2026/06/4deb956d6b298c8.png)\n\n![AI comic creation scene, creat](https://blog.xxyye.com/wp-content/uploads/2026/06/4c5a46dbf4df883.png)\n\nr: name 'x' is not defined
  • ❌ 写了两个 count 变量,不知道哪个覆盖了哪个

这些问题,全是变量和作用域没搞明白惹的祸

学完能解决

  • ✅ 正确声明和赋值变量
  • ✅ 搞懂局部变量和全局变量的区别
  • ✅ 写出不会互相「打架」的代码

🧱 基础 25 分钟:核心概念

1. 变量是什么?

生活类比:变量就像是一个带标签的收纳盒。你在盒子上贴个标签(变量名),里面放东西(数据)。下次想拿东西,直接喊标签名字就行。

为什么要用:程序运行需要记忆,变量就是记忆的载体。没有变量,你每写一个数字都要重复输入,太麻烦了。

怎么用

# 声明一个变量,给它起个名字
name = "小明"
age = 18
price = 19.9

print(name)
print(age)

运行结果:

小明
18

nameageprice 就是变量名,= 是赋值符号,意思是「把右边的值放进左边的盒子里」。

注意!Python 的变量不需要声明类型,你直接写 name = "小明" 就 OK 了,计算机会自动记住这是字符串。比起 JavaScript 的 var/let/const,Python 简洁多了。

2. 变量命名规则(新手必看)

生活类比:变量名就像是给宠物起名字,总不能叫「汪汪 123」吧?虽然能叫,但听起来不太正经。

规则

# ✅ 合法的变量名
user_name = "张三"      # 下划线连接
userAge = 25            # 驼峰命名(Python不推荐但能用)
_private = "隐藏的"      # 以下划线开头,有特殊含义

# ❌ 非法的变量名(会报错!)
# 2nd_place = "第二名"   # 不能以数字开头
# user-name = "李四"     # 不能用中划线
# user name = "王五"     # 不能有空格

Python 惯例:Python 社区约定俗成用小写字母 + 下划线,比如 max_valueuser_name。看到这种命名风格,你就知道这是正经 Python 代码。

3. 变量的数据类型(先混个脸熟)

Python 里变量有几种「类型」,先知道 3 个最常用的:

# 字符串 - 文字
greeting = "你好,世界"

# 整数 - 整数
count = 42

# 浮点数 - 小数
price = 19.99

print(type(greeting))  # <class 'str'>
print(type(count))     # <class 'int'>
print(type(price))     # <class 'float'>

type() 函数能查看一个变量的「类型」。这就好比收纳盒也分塑料盒、纸盒、玻璃盒——虽然都能装东西,但用途不同。

4. 赋值与修改变量

生活类比:你往盒子里放了个苹果,想换成香蕉?直接把苹果拿出来,放进香蕉就行了。变量赋值就是这样,覆盖式替换。

# 第一次赋值
score = 100
print(score)  # 100

# 第二次赋值,覆盖掉第一次的值
score = 90
print(score)  # 90

# 基于原来的值做修改
score = score + 10  # 相当于取出100,加10,再放回去
print(score)  # 110

简写形式

score = 100
score += 10   # 等价于 score = score + 10
print(score)  # 110

5. 多个变量同时赋值

# 交换两个变量的值(经典面试题)
a = 1
b = 2
a, b = b, a  # Python 特有语法,一行搞定交换
print(a, b)  # 2 1

# 链式赋值(多个变量指向同一个值)
x = y = z = 0
print(x, y, z)  # 0 0 0

6. 作用域:变量在哪儿「看得见」

生活类比:想象公司组织架构——部门内部的事,只有那个部门的人知道;全公司的事,所有人都能用。程序也一样,有些变量只能在一个函数里用,有些变量整个程序都能用。

全局变量 vs 局部变量

# 全局变量 - 定义在函数外面的变量
total = 1000  # 整个程序都能看见它

def calculate():
# 局部变量 - 只在函数内部有效
discount = 0.8
result = total * discount  # 这里能用 total
print(f"函数内部:discount = {discount}")

calculate()
print(f"函数外部:total = {total}")
# print(discount)  # ❌ 这行会报错!因为 discount 是局部变量

运行结果:

函数内部:discount = 0.8
函数外部:total = 1000

global 关键字:我要在函数里改全局变量

count = 0  # 全局变量

def increment():
global count  # 声明我要用外面的 count
count += 1
print(f"函数里:count = {count}")

increment()
increment()
print(f"函数外:count = {count}")

运行结果:

函数里:count = 1
函数里:count = 2
函数外:count = 2

注意! global 虽香,但新手尽量少用,因为会让代码难调试。更好的做法是通过参数传递、返回值来处理。


🔥 实战 35 分钟:3 个递进的小项目

项目 1(5 分钟):个人信息存储与展示

场景:做一个简单的「名片生成器」,存储并展示个人信息。

完整代码

# 名片信息
name = "李明"
job = "Python 讲师"
company = "代码大学"
email = "liming@codecollege.com"
years_experience = 5

# 打印名片
print("=" * 30)
print("【名片】")
print(f"姓名:{name}")
print(f"职位:{job}")
print(f"公司:{company}")
print(f"邮箱:{email}")
print(f"工龄:{years_experience} 年")
print("=" * 30)

预期输出

==============================
【名片】
姓名:李明
职位:Python 讲师
公司:代码大学
邮箱:liming@codecollege.com
工龄:5 年
==============================

解释:我们把个人信息存进变量,然后用 f-string(格式化字符串)把它们拼到一句话里。f"姓名:{name}"{name} 会被变量的实际值替换。


项目 2(15 分钟):学生成绩统计

场景:读取一份学生成绩数据,计算平均分、最高分、最低分。

完整代码

# 学生成绩数据(模拟从 CSV 读取的效果)
scores = [85, 92, 78, 96, 67, 88, 73, 95, 81, 70]

# 统计数据
total = sum(scores)           # 总分
average = total / len(scores) # 平均分
max_score = max(scores)       # 最高分
min_score = min(scores)       # 最低分

# 找出最高分和最低分对应的学生(假设学号就是索引+1)
top_student = scores.index(max_score) + 1
bottom_student = scores.index(min_score) + 1

# 打印报告
print("【期末成绩统计报告】")
print(f"参赛人数:{len(scores)} 人")
print(f"平均分:{average:.2f} 分")  # :.2f 表示保留两位小数
print(f"最高分:{max_score} 分(学号:{top_student})")
print(f"最低分:{min_score} 分(学号:{bottom_student})")
print(f"成绩分布:{scores}")

预期输出

【期末成绩统计报告】
参赛人数:10 人
平均分:82.50 分
最高分:96 分(学号:4)
最低分:67 分(学号:5)
成绩分布:[85, 92, 78, 96, 67, 88, 73, 95, 81, 70]

解释:这个项目展示了变量的实际用途——把零散的数据存进列表,用 sum()max()min() 这些函数做统计。变量 totalaverage 存储的是「计算结果」,方便后续使用和打印。


项目 3(15 分钟):待办事项管理器

场景:做一个命令行待办清单,能添加、查看、完成事项。

完整代码

# 待办清单数据
todos = []

def show_menu():
print("\n【待办清单 v1.0】")
print("1. 查看待办")
print("2. 添加待办")
print("3. 完成待办")
print("4. 退出")

def add_todo():
item = input("请输入新事项:")
todos.append(item)
print(f"✅ 已添加:{item}")

def show_todos():
if not todos:
    print("📭 清单是空的")
else:
    print(f"\n📋 共 {len(todos)} 项待办:")
    for i, todo in enumerate(todos, 1):
        print(f"  {i}. {todo}")

def complete_todo():
show_todos()
if todos:
    choice = int(input("请输入要完成的事项编号:"))
    if 1 <= choice <= len(todos):
        completed = todos.pop(choice - 1)
        print(f"🎉 已完成:{completed}")

# 主程序循环
while True:
show_menu()
choice = input("请选择操作(1-4):")

if choice == "1":
    show_todos()
elif choice == "2":
    add_todo()
elif choice == "3":
    complete_todo()
elif choice == "4":
    print("👋 再见!")
    break
else:
    print("⚠️ 无效选择,请重试")

预期输出(交互示例):

【待办清单 v1.0】
1. 查看待办
2. 添加待办
3. 完成待办
4. 退出
请选择操作(1-4):2
请输入新事项:买牛奶
✅ 已添加:买牛奶

请选择操作(1-4):2
请输入新事项:写代码
✅ 已添加:写代码

请选择操作(1-4):1

📋 共 2 项待办:
1. 买牛奶
2. 写代码

请选择操作(1-4):3
1. 买牛奶
2. 写代码
请输入要完成的事项编号:1
🎉 已完成:买牛奶

请选择操作(1-4):4
👋 再见!

解释todos 是全局变量,存储所有待办事项。add_todo()append() 添加,complete_todo()pop() 移除。列表是可变变量,所以在函数里直接修改 todos 是有效的。


💪 进阶 20 分钟:常见坑 + 性能小贴士

坑 1:变量未初始化就使用

# ❌ 错误示例
print(result)  # 还没赋值就用,报错:NameError
result = 100

# ✅ 正确示例
result = 100
print(result)  # 先赋值,后使用

坑 2:全局变量和局部变量混淆

# ❌ 错误示例
count = 10

def increment():
count = count + 1  # 这里 count 被当成局部变量,但还没赋值!
print(count)

increment()  # 报错:UnboundLocalError

# ✅ 正确示例 1:用 global
count = 10

def increment():
global count
count = count + 1
print(count)

increment()  # 11

# ✅ 正确示例 2:通过参数和返回值(推荐)
count = 10

def increment(val):
return val + 1

count = increment(count)
print(count)  # 11

坑 3:变量名拼写错误(大小写敏感)

# ❌ 错误示例
UserName = "张三"
print(user_name)  # 大小写不对,报错

# ✅ 正确示例
user_name = "张三"
print(user_name)  # 正常

Python 的变量名是大小写敏感的,user_nameUser_Name 是两个完全不同的变量!

坑 4:以为修改了全局变量(其实没有)

# ❌ 错误示例
greetings = ["你好", "hello"]

def add_greeting():
greetings.append("hola")  # 这个确实改了全局变量

add_greeting()
print(greetings)  # ['你好', 'hello', 'hola'] 改了?

# 但是这样:
def replace_greeting():
greetings = ["ni hao"]  # 这是新建了一个局部变量!

replace_greeting()
print(greetings)  # ['你好', 'hello', 'hola'] 没变!

# ✅ 正确做法:如果要重新赋值整个列表,用 global
def replace_greeting_correct():
global greetings
greetings = ["ni hao"]

replace_greeting_correct()
print(greetings)  # ['ni hao']

记住list.append()list.remove() 这种原地修改的方法会影响到全局变量,但直接用 = 赋值是创建新局部变量。

坑 5:循环变量泄漏到全局

# ❌ 警告示例
for i in range(5):
print(i)

print(f"循环结束后 i = {i}")  # i = 4,变量泄漏了!

# ✅ 正确做法:明确变量的作用域
def process():
for i in range(5):
    print(i)
# i 只在函数内部有效

process()
# print(i)  # 这里访问不到 i,安全!

调试技巧:print 大法

# 简单粗暴但有效的调试方法
def buggy_function(x, y):
print(f"进入函数:x={x}, y={y}")  # 打印输入
result = x / y
print(f"计算结果:result={result}")  # 打印中间结果
return result

buggy_function(10, 2)
# 输出:
# 进入函数:x=10, y=2
# 计算结果:result=5.0

print() 调试就像给程序加监控摄像头,哪里不对打哪里,简单但实用。


✏️ 练习题

练习 1(2 分钟):变量赋值

  • 输入:无
  • 预期输出:Hello, Python!
  • 提示:message 变量存字符串,用 print() 打印

练习 2(2 分钟):计算圆的面积

  • 输入:radius = 5(半径)
  • 预期输出:面积是 78.54(保留两位小数,π 取 3.14159)
  • 提示:面积公式 πr²,用 f"{area:.2f}" 格式化

练习 3(3 分钟):成绩等级判断

  • 输入:score = 85
  • 预期输出:等级是 B(90 以上 A,80-89 是 B,70-79 是 C,70 以下 D)
  • 提示:用 if/elif/else 判断,在项目 2 的代码基础上改

练习 4(5 分钟):列表元素统计

  • 输入:numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • 预期输出:奇数有 5 个,偶数有 5 个
  • 提示:用循环遍历列表,if 判断奇偶,累加计数

练习 5(5 分钟):找出报错原因

  • 输入:以下代码
def test():
value = 100
print(value)

print(value)  # 这行报错
  • 预期输出:说明为什么报错,如何修复
  • 提示:作用域问题,value 是局部变量

作业:做一个「个人账本工具」

需求描述:命令行账本,能记录收入和支出,查询余额。

功能点
1. 添加收入/支出(金额 + 说明)
2. 查看当前余额
3. 查看收支明细(列出所有记录)
4. 退出

加分项
1. 收支记录带时间戳
2. 能删除某条记录

验收标准
- 程序能正常运行
- 余额计算正确
- 代码有适当注释

提交方式:评论区贴代码或 GitHub 链接


📚 总结 + 资源

一句话总结:变量是程序的「记忆」,声明变量用 = 赋值,作用域决定变量在哪儿「看得见」——局部变量只在函数内有效,全局变量整个程序都能用。

延伸学习资源

  1. Python 官方文档:数据模型-变量 —— 权威、全面,但有点枯燥
  2. 《Python编程:从入门到实践》第二章 —— 循序渐进,适合小白
  3. 视频:B站 - Python 变量与数据类型 —— 视觉化学习更友好

互动钩子:你在写代码时,因为变量作用域踩过什么坑?是全局变量被覆盖了,还是局部变量取不出来?评论区聊聊,老粉优先回复!


💡 下章剧透:学会了存放数据,下一章我们要聊聊这些数据都有哪些「类型」——字符串、数字、布尔值……还有它们之间怎么互相转换。数据类型搞错了,程序会闹笑话的哦~

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。