Python for 循环
上一节使用 while 控制重复过程,但需要我们自己准备循环变量、判断条件和更新操作。
现在遇到两个常见任务:
- 已知要重复多少次,例如连续输出 5 次练习记录;
- 已经有一组内容,例如字符串,需要逐个取出并处理。
如果每轮都手动取值或更新,代码很快会变得重复。for 可以自动取出下一项,range() 可以生成需要的重复次数。本章再继续解决筛选内容、选择循环类型和处理多层重复的问题。
遍历一组内容:for
先解决第一个任务:依次打印字符串 Python 中的每个字符。
for 循环可以先理解为:从一组内容中按顺序取值,每取出一个值,就执行一次循环体。
for 变量 in 一组内容:
每次取值后执行的代码for char in "Python":
print(char)运行结果:
P
y
t
h
o
n循环开始后,char 会依次得到 "P"、"y"、"t"、"h"、"o" 和 "n"。字符串中的字符全部取完后,循环自动结束。
这里不需要提前定义 char,也不需要手动修改它。for 会在每轮循环开始时自动取出下一个值。
控制重复次数:range()
如果手里没有现成的一组内容,只知道“要执行几次”,应该怎样让 for 按次数运行?
需求:让代码固定执行 5 次,并输出每轮拿到的编号。通常会让 for 配合 range() 使用。
for number in range(5):
print(number)运行结果:
0
1
2
3
4range(5) 依次产生 0、1、2、3、4,所以循环执行 5 次。最容易记错的是:
range() 包含起始值,不包含结束值。
range() 的三种写法
range() 有三种常用写法:
range(stop)
range(start, stop)
range(start, stop, step)| 参数 | 作用 | 默认值 |
|---|---|---|
start | 起始值,会被包含 | 0 |
stop | 结束值,不会被包含 | 必须提供 |
step | 每次变化的步长 | 1 |
for 可以直接遍历 range() 产生的整数范围,不需要先使用 list() 转换。
只提供一个参数时,这个参数表示结束值:
for number in range(5):
print(number, end=" ")运行结果:
0 1 2 3 4同时提供起始值和结束值,可以生成 1 到 5:
for number in range(1, 6):
print(number, end=" ")运行结果:
1 2 3 4 5第三个参数用于控制步长。例如,从 0 开始,每次增加 2:
for number in range(0, 10, 2):
print(number, end=" ")运行结果:
0 2 4 6 8步长也可以是负数。此时起始值要大于结束值:
for number in range(5, 0, -1):
print(number, end=" ")运行结果:
5 4 3 2 1如果只关心重复次数,不需要使用每轮产生的数字,可以把循环变量写成 _:
for _ in range(3):
print("继续练习")_ 仍然是变量,只是按照常见约定表示“这个值不会在后面使用”。
遍历与筛选
逐个取出值之后,如果还要挑出满足条件的内容,就把 for 和 if 组合起来。
有时我们不只是要取出每个值,还要检查当前值是否符合条件。“遍历”就是按照某种顺序,把一组内容逐个取出。除了 range(),for 还可以遍历字符串,以及后续会学习的列表、元组、集合和字典。
下面统计字符串中包含多少个字母 o:
text = "hello world"
count = 0
for char in text:
if char == "o":
count += 1
print(f"字母 o 出现了 {count} 次")运行结果:
字母 o 出现了 2 次这段代码把循环和判断组合在一起:for 负责逐个取出字符,if 负责判断当前字符是不是 "o"。
for 与 while 的选择
同一个重复任务有时两种循环都能完成,应该根据什么来选择?
for 和 while 都能实现循环,但它们适合处理的问题不同:
| 场景 | 更适合的循环 |
|---|---|
| 按顺序取出一组内容 | for |
| 已经明确重复次数 | for |
| 条件成立时持续执行 | while |
| 无法提前确定循环次数 | while |
例如:
- 连续完成 5 次练习,可以使用
for - 逐个检查字符串中的字符,可以使用
for - 持续接收输入,直到用户输入
q,更适合使用while
这不是强制规则,但能帮助我们快速选择结构。只要循环过程依赖的是“一组待处理的内容”,通常优先考虑 for。
嵌套 for:分层处理
如果任务同时包含“多行”和“每行多个内容”两层重复,怎样避免把每一行都手写?
如果一个任务同时有“多行”和“每行多个内容”两层重复,就需要在 for 内再写一个 for。和嵌套 while 一样,外层循环通常控制行,内层循环负责每一行中的重复内容。
案例:星号三角形
需求:输出一个正左角形。
*
**
***
****
*****for row in range(1, 6):
# 当前是第几行,就打印几颗星
for col in range(1, row + 1):
print("*", end="")
# 当前行打印完成后换行
print()外层的 row 依次得到 1 到 5,负责决定当前是第几行。内层循环负责打印当前行的星号。
当 row 等于 3 时:
range(1, row + 1)相当于range(1, 4)col依次得到1、2、3- 内层循环执行 3 次,打印 3 颗星
- 内层循环结束后,最后一个
print()负责换行
这里写成 row + 1,是因为 range() 不包含结束值。
练习:用空格调整图形对齐
在星号左侧补充空格,把图形调整为正右角形:
*
**
***
****
*****可以先分析每一行的组成:
- 第 1 行:4 个空格,1 颗星
- 第 2 行:3 个空格,2 颗星
- 第 5 行:0 个空格,5 颗星
先根据这个规律自己完成代码,再展开参考答案。
参考答案
for row in range(1, 6):
# 行号越大,左侧空格越少
for _ in range(5 - row):
print(" ", end="")
# 当前是第几行,就打印几颗星
for _ in range(row):
print("*", end="")
print()前面已经分别解决了遍历、筛选和嵌套循环。接下来用两个完整任务把这些方法串起来。
案例:九九乘法表
需求:输出九九乘法表,并让第 n 行只显示前 n 个乘法表达式。
上一节使用嵌套 while 输出了九九乘法表。换成 for 后,不再需要手动初始化和更新 row、col。
for row in range(1, 10):
# 当前是第几行,就输出几个乘法表达式
for col in range(1, row + 1):
print(f"{col} × {row} = {col * row}", end="\t")
print()运行逻辑与上一节相同:
- 外层循环控制 9 行
- 内层循环从
1遍历到当前行号 - 每轮内层循环输出一个乘法表达式
- 当前行结束后,使用
print()换行
当 row 等于 9 时,range(1, row + 1) 就是 range(1, 10),内层循环会输出 9 个乘法表达式。
案例:寻找水仙花数
需求:找出所有三位水仙花数。水仙花数是一个三位数,它每一位数字的三次方之和等于它本身。例如:
153 = 1³ + 5³ + 3³要找出所有三位水仙花数,可以把任务拆成三步:
- 使用
for依次取出100到999 - 分别计算当前数字的百位、十位和个位
- 使用
if判断三位数字的三次方之和是否等于原数字
先练习遍历所有三位数:
for number in range(100, 1000):
print(number)接着加入数位拆分和判断:
for number in range(100, 1000):
hundreds = number // 100
tens = number // 10 % 10
ones = number % 10
if hundreds ** 3 + tens ** 3 + ones ** 3 == number:
print(number)运行结果:
153
370
371
407以 153 为例:
153 // 100得到百位数字1153 // 10 % 10得到十位数字5153 % 10得到个位数字3
for 负责检查每一个三位数,if 只保留满足条件的数字。这样就把“遍历”和“判断”各自的职责分开了。
常见问题
range() 不包含结束值
range(1, 5) 产生的是 1、2、3、4,不包含 5。如果需要得到 1 到 5,结束值要写成 6。
循环变量的自动更新
for 会在每轮开始时自动为循环变量取下一个值。通常不需要再写 number += 1,否则代码容易让人误以为它能控制下一轮取值。
for number in range(3):
print(number)小结
本章沿着五个问题推进:
- 一组内容如何逐个处理?使用
for - 重复次数如何控制?使用
range(),并牢记结束值不包含在内 - 如何只保留满足条件的内容?用
for配合if for和while如何选择?看任务依赖内容还是条件- 多行多列的任务如何拆分?用嵌套循环让外层控制行、内层处理每行内容