第2章 2.4 for 循环与 range()
上一章我们学会了 while 循环,发现它就像天气预报的「明天继续下雨吗?」一样,符合条件就反复执行。但你有没有觉得 while 循环有点「盲」?它只知道问「对不对」,却不知道具体数到哪儿了。比如你想让程序「把 1 到 100 的数字一个个打印出来」,用 while 得手动设个计数器,还得记得每次 +1,一不小心就搞出个死循环。
这一章我们学个更聪明的办法——for 循环配合 range(),就像有人帮你数数,你只管说「从几数到几」就行。
🎯 开场 3 分钟:为什么要学这个?
想象这样一个场景:月底了,你对着 Excel 表格发呆,老板说「把这 500 行数据里每个用户的消费额都加 10%」。你一个个手改?改到明年吧。
或者你想做个「点名器」,随机挑一个同学回答问题,结果 while 循环要么停不下来,要么根本没按预期次数执行。
学完这章你能:
- 用 for + range() 精确控制循环次数,不再靠「感觉差不多」
- 遍历列表、字符串等可迭代对象,批量处理数据
- 用 enumerate 同时拿到索引和值,用 zip 合并两个列表一起遍历
🧱 基础 25 分钟:核心概念
什么是 range()?—— 帮你数数的工具
range() 就像一个报数机器人,你告诉它从几开始、到哪结束,它就帮你生成一串数字。
# range(5) 生成 0 到 4
for i in range(5):
print(i)
输出:
0
1
2
3
4
这太有用了!想象你在排队,range(5) 就是「第 0 个人、第 1 个人……第 4 个人」,不用自己数,它帮你搞定。
range() 的三种打开方式
方式 1:range(stop) —— 从 0 数到 stop-1
for i in range(10):
print(f"第 {i} 次执行")
方式 2:range(start, stop) —— 从 start 数到 stop-1
for i in range(5, 10):
print(i) # 输出 5, 6, 7, 8, 9
就像「从第 5 节课上到第 9 节课」,包含开头不包含结尾。
方式 3:range(start, stop, step) —— 还能跳着数
for i in range(0, 10, 2):
print(i) # 输出 0, 2, 4, 6, 8
step=2 就是「每数一个跳过一个」,相当于「偶数序列」。

什么是 for 循环?—— 流水线上的取货员
如果说 while 是「站门口问对不对」,for 循环就是「沿着流水线一个个取东西」。
水果列表 = ["苹果", "香蕉", "橘子"]
for 水果 in 水果列表:
print(f"正在处理: {水果}")
输出:
正在处理: 苹果
正在处理: 香蕉
正在处理: 橘子
注意!这里的 水果 是变量名,你可以随便起,但一般起有意义的名字。看到这里你可能在想:水果列表里的东西是一个个取出来的,那 range() 生成的数字怎么用 for 取出来?
for i in range(5):
print(f"计数器 i = {i}")
输出:
计数器 i = 0
计数器 i = 1
计数器 i = 2
计数器 i = 3
计数器 i = 4
range(5) 相当于一个「隐藏的列表」[0, 1, 2, 3, 4],for 循环帮你一个个取出来。
enumerate:同时拿到索引和值
有时候你不仅想知道「当前是什么」,还想知道「这是第几个」。比如打印「第 1 名、苹果」「第 2 名、香蕉」:
水果列表 = ["苹果", "香蕉", "橘子"]
for 索引, 水果 in enumerate(水果列表):
print(f"第 {索引 + 1} 个水果是: {水果}")
输出:
第 1 个水果是: 苹果
第 2 个水果是: 香蕉
第 3 个水果是: 橘子
enumerate 会把列表变成「(索引, 值)`元组」的序列,for 循环帮你解开。注意索引从 0 开始,所以要 +1 才符合人类习惯。

zip:两个列表同步遍历
如果你有两个列表,想「第一个列表的第 0 个配对第二个列表的第 0 个」:
names = ["小明", "小红", "小李"]
scores = [85, 92, 78]
for name, score in zip(names, scores):
print(f"{name} 的分数是 {score}")
输出:
小明的分数是 85
小红的分数是 92
小李的分数是 78
zip 就像「拉链」一样,把两个列表「咬合」在一起。短的那个列表决定了遍历次数——如果列表长度不一样,多余的部分会被忽略。
🔥 实战 35 分钟:3 个递进的小项目
项目 1(5 分钟):自动打印课程表
场景:你是班长,要打印这周前 3 天的课程安排。
# 课程表
课程列表 = ["周一:Python 基础", "周二:数据结构", "周三:算法",
"周四:数据库", "周五:网络编程"]
# 用 range 只打印前 3 天
print("=== 本周前 3 天课程 ===")
for i in range(3):
print(课程列表[i])
输出:
=== 本周前 3 天课程 ===
周一:Python 基础
周二:数据结构
周三:算法
解释:range(3) 生成 [0, 1, 2],刚好对应前 3 个课程。这比 while 循环简单多了,不用手动维护计数器。
项目 2(15 分钟):批量计算员工年终奖
场景:公司要根据绩效计算年终奖,绩效 A 发 20% 年终奖,B 发 15%,C 发 10%。从 CSV 读取数据。
# 模拟 CSV 数据(实际可以用 open().readlines() 读真实文件)
员工数据 = [
{"姓名": "张三", "月薪": 8000, "绩效": "A"},
{"姓名": "李四", "月薪": 6000, "绩效": "B"},
{"姓名": "王五", "月薪": 7000, "绩效": "A"},
{"姓名": "赵六", "月薪": 5000, "绩效": "C"},
]
# 绩效奖金比例
奖金比例 = {"A": 0.20, "B": 0.15, "C": 0.10}
print("=== 年终奖明细 ===")
总奖金支出 = 0
for 员工 in 员工数据:
姓名 = 员工["姓名"]
月薪 = 员工["月薪"]
绩效 = 员工["绩效"]
# 年终奖 = 月薪 × 12 × 奖金比例
比例 = 奖金比例[绩效]
年终奖 = 月薪 * 12 * 比例
总奖金支出 += 年终奖
print(f"{姓名}:月薪 {月薪}元,绩效{绩效},年终奖 {年终奖:.2f}元")
print(f"\n公司年度奖金总支出:{总奖金支出:.2f}元")
输出:
=== 年终奖明细 ===
张三:月薪 8000元,绩效A,年终奖 19200.00元
李四:月薪 6000元,绩效B,年终奖 10800.00元
王五:月薪 7000元,绩效A,年终奖 16800.00元
赵六:月薪 5000元,绩效C,年终奖 6000.00元
公司年度奖金总支出:52800.00元
解释:for 循环遍历每个员工的字典,用格式化字符串 f"{年终奖:.2f}" 保留两位小数,% 操作符是老式写法。
项目 3(15 分钟):待办事项管理小工具
场景:做一个命令行待办清单,可以添加任务、查看任务、标记完成。
待办列表 = []
def 显示菜单():
print("\n=== 待办清单 ===")
print("1. 添加任务")
print("2. 查看任务")
print("3. 标记完成")
print("4. 退出")
def 添加任务():
任务 = input("请输入新任务:")
待办列表.append({"任务": 任务, "完成": False})
print(f"已添加:{任务}")
def 查看任务():
if not 待办列表:
print("列表是空的!")
return
print("\n当前待办:")
for 索引, 条目 in enumerate(待办列表):
状态 = "✓" if 条目["完成"] else "○"
print(f"{索引 + 1}. [{状态}] {条目['任务']}")
def 标记完成():
查看任务()
if not 待办列表:
return
序号 = int(input("请输入要完成的任务序号:"))
if 1 <= 序号 <= len(待办列表):
待办列表[序号 - 1]["完成"] = True
print(f"已完成:{待办列表[序号 - 1]['任务']}")
else:
print("序号无效!")
# 主循环
while True:
显示菜单()
选择 = input("请选择 (1-4):")
if 选择 == "1":
添加任务()
elif 选择 == "2":
查看任务()
elif 选择 == "3":
标记完成()
elif 选择 == "4":
print("再见!")
break
else:
print("无效选择,请重试!")
运行效果示例:
=== 待办清单 ===
1. 添加任务
2. 查看任务
3. 标记完成
4. 退出
请选择 (1-4):1
请输入新任务:写周报
已添加:写周报
请选择 (1-4):2
当前待办:
1. [○] 写周报
请选择 (1-4):3
1. [○] 写周报
请输入要完成的任务序号:1
已完成:写周报
解释:这个项目组合了 for 循环遍历 + enumerate 获取索引 + while 循环做主菜单。实际开发中可以用文件读写把数据持久化。
💪 进阶 20 分钟:常见坑 + 性能小贴士
坑 1:range() 容易写错边界
# ❌ 错误:想打印 1-10,写成了 range(10)
for i in range(10):
print(i) # 只会打印 0-9
# ✅ 正确:明确要 1-10,用 range(1, 11)
for i in range(1, 11):
print(i) # 打印 1-10
记住:range() 是「包头不包尾」,就像「第 1 节课到第 3 节课」指的是 1、2、3,不是 1、2、3、4。
坑 2:修改列表时别用 for 遍历
# ❌ 错误:边遍历边删除可能导致漏删
数字列表 = [1, 2, 3, 4, 5]
for 数字 in 数字列表:
if 数字 < 3:
数字列表.remove(数字) # 可能漏掉某些元素
# ✅ 正确:用切片创建副本,或者用列表推导式
数字列表 = [1, 2, 3, 4, 5]
数字列表 = [x for x in 数字列表 if x >= 3] # 列表推导式
print(数字列表) # [3, 4, 5]
坑 3:zip() 当列表长度不同时会丢数据
# ❌ 容易忽略:长度不同的列表 zip 会截断
a = [1, 2, 3, 4]
b = ["甲", "乙"]
for 数字, 字母 in zip(a, b):
print(f"{数字}-{字母}")
# 只输出:1-甲, 2-乙,4 被丢弃了
# ✅ 正确:先检查长度,或用 itertools.zip_longest
from itertools import zip_longest
a = [1, 2, 3, 4]
b = ["甲", "乙"]
for 数字, 字母 in zip_longest(a, b, fillvalue="?"):
print(f"{数字}-{字母}")
# 输出:1-甲, 2-乙, 3-?, 4-?
坑 4:enumerate 的索引别当列表下标直接用
# ❌ 错误:以为索引 1 对应第二个元素,但原始列表可能不一致
原始列表 = ["a", "b", "c"]
删除后的列表 = []
for 索引, 值 in enumerate(原始列表):
删除后的列表.append(值)
if 值 == "b":
del 原始列表[索引] # 索引已经不对了!
坑 5:for 循环后用 else(Python 特有语法)
# Python 的 for...else:循环正常结束才执行 else
for i in range(3):
print(i)
else:
print("循环正常结束")
# 输出:0, 1, 2, 循环正常结束
# 如果被 break 打断,else 不会执行
for i in range(3):
if i == 1:
break
print(i)
else:
print("循环正常结束")
# 只输出 0,不输出 else
性能小贴士:列表推导式比 for + append 更快
# ❌ 慢:循环追加
结果 = []
for i in range(1000):
结果.append(i * 2)
# ✅ 快:列表推导式(内部用 C 语言实现)
结果 = [i * 2 for i in range(1000)]
调试技巧:用 enumerate 打印关键变量
# 不知道循环哪里出问题了?把索引和值都打印出来
数据 = ["苹果", "香蕉", "橘子"]
for 索引, 值 in enumerate(数据):
print(f"DEBUG: 索引={索引}, 值={值}, 列表长度={len(数据)}")
if 索引 > 10: # 防止无限循环
print("疑似死循环,强制退出")
break
✏️ 练习题
练习 1(2 分钟):数到哪了?
- 输入:无
- 预期输出:打印 5 到 15 的所有整数
- 提示:range() 的第二个参数是结束值,要+1
for i in range(5, 16):
print(i)
练习 2(2 分钟):偶数之和
- 输入:无
- 预期输出:计算 1-10 所有偶数的和,输出
偶数之和为: 30 - 提示:用 range(2, 11, 2) 生成偶数
total = 0
for i in range(2, 11, 2):
total += i
print(f"偶数之和为: {total}")
练习 3(3 分钟):成绩统计
- 输入:见代码
- 预期输出:打印不及格(<60)的人数
- 提示:for 循环遍历列表,加个 if 判断
分数列表 = [55, 78, 92, 45, 88, 60, 73]
不及格人数 = 0
for 分数 in 分数列表:
if 分数 < 60:
不及格人数 += 1
print(f"不及格人数:{不及格人数}")
练习 4(3 分钟):enumerate 实战
- 输入:列表
["猫", "狗", "鸟"] - 预期输出:
1. 猫 2. 狗 3. 鸟(每个一行) - 提示:索引要 +1 才符合从 1 开始的人类习惯
动物列表 = ["猫", "狗", "鸟"]
for 索引, 动物 in enumerate(动物列表, 1):
print(f"{索引}. {动物}")
练习 5(5 分钟):找错题
- 输入:以下代码
- 预期输出:分析为什么只打印到 0-8 而不是 0-9
- 提示:range() 的包头不包尾特性
# 这段代码期望打印 0-9,但实际只打印到 8
# 请找出原因并修复
for i in range(0, 10, 1): # 实际上 range(10) 就够了
print(i)
作业:做一个「个人消费记账本」
需求描述:
做一个命令行记账工具,记录你的日常消费,月底统计各类支出占比。
功能点:
1. 添加消费记录(日期、分类、金额、备注)
2. 查看所有记录(带序号)
3. 按分类统计总支出
4. 显示支出最高的 Top 3 分类
加分项:
1. 数据保存到文件(下次启动还能用)
2. 支持删除某条记录
验收标准:
- 能跑起来
- 输入数据后能正确统计
- 代码有中文注释
提交方式:评论区贴代码或 GitHub 链接
📚 总结 + 资源
这章学了啥:
- range() 帮你生成数字序列,是 for 循环的黄金搭档
- for 变量 in 可迭代对象 是 Python 最常用的循环形式
- enumerate 拿索引、zip 合并遍历,让数据处理更灵活
延伸学习:
- 官方文档:内置类型 - 序列类型
- 书籍:《Python编程:从入门到实践》第 9 章
- 视频:B 站小甲鱼《零基础学 Python》第 35-40 集
互动钩子:
你在工作/学习中有没有遇到「要重复处理一堆数据」的场景?是用什么方法解决的?评论区聊聊,老粉优先回复!
下一章我们要综合运用 for 循环和 while 循环,做两个经典实战项目:猜数字游戏 和 九九乘法表,看看两种循环怎么配合使用才能威力最大化。

评论(0)