Python 循环图解:看见每一轮发生了什么
用三条订单逐轮图解 for 循环:当前项怎样变化、条件是否命中、累计值如何更新,以及 continue 与 break 分别跳过了什么。
本文目录 5 节 · 点击展开
在 Excel 里,一条公式向下填充后,会依次处理每一行。Python 的 for 循环也在重复处理数据,但它多做了一件不容易被眼睛发现的事:每一轮都会把变量名绑定到下一条数据,再从循环体第一行向下执行。
这一篇只跟踪三条订单。你会看见当前订单怎样从 A001 变成 A002、A003,为什么退款订单没有进入累计分支,以及金额怎样从 0.0 走到 328.0。
三条订单怎样进入循环
先准备一批订单。外层的方括号表示这是一个列表,列表里有三个字典;每个字典就是一条订单:
orders = [
{"order_no": "A001", "status": "已支付", "amount": 129.0},
{"order_no": "A002", "status": "已退款", "amount": 88.0},
{"order_no": "A003", "status": "已支付", "amount": 199.0},
]
当 Python 执行下面这行时,变量 order 一次只代表列表中的一条订单:
for order in orders:
print(order["order_no"])
运行顺序是:
第 1 轮:order → A001
第 2 轮:order → A002
第 3 轮:order → A003
列表已用完:离开循环
for 不会同时处理三条数据。它先拿出一条,执行完缩进的循环体,再回到顶部拿下一条。
完整任务:筛选已支付订单并累计金额
现在给循环加上判断和两个累计器。代码可以直接复制运行:
orders = [
{"order_no": "A001", "status": "已支付", "amount": 129.0},
{"order_no": "A002", "status": "已退款", "amount": 88.0},
{"order_no": "A003", "status": "已支付", "amount": 199.0},
]
paid_count = 0
total = 0.0
for order in orders:
is_paid = order["status"] == "已支付"
if is_paid:
paid_count += 1
total += order["amount"]
print(f"paid_count = {paid_count}")
print(f"total = {total}")
输出:
paid_count = 2
total = 328.0
paid_count += 1 等同于 paid_count = paid_count + 1;total += order["amount"] 也是先用旧值完成加法,再把名字重新绑定到新结果。关键不是背写法,而是看见每轮的旧值和新值。
- 01 · 当前行
for order in ordersorder → A001 - 02 · 当前行
is_paid = order[“status”] == “已支付""已支付” == “已支付” → True - 03 · 条件
if is_paidTrue · 选中,进入分支
- 04 · 数量
paid_count += 10 → 1 - 05 · 金额
total += 129.00.0 → 129.0
- 01 · 当前行
for order in ordersorder → A002 - 02 · 当前行
is_paid = order[“status”] == “已支付""已退款” == “已支付” → False - 03 · 条件
if is_paidFalse · 未选中,跳过分支
- 04 · 未执行
paid_count += 11 → 1· 保持不变 - 05 · 未执行
total += 88.0129.0 → 129.0· 保持不变
- 01 · 当前行
for order in ordersorder → A003 - 02 · 当前行
is_paid = order[“status”] == “已支付""已支付” == “已支付” → True - 03 · 条件
if is_paidTrue · 选中,进入分支
- 04 · 数量
paid_count += 11 → 2 - 05 · 金额
total += 199.0129.0 → 328.0
- 开始0
- 第 1 轮1
- 第 2 轮1
- 第 3 轮2
- 开始0.0
- 第 1 轮129.0
- 第 2 轮129.0
- 第 3 轮328.0
paid_count = 2total = 328.0第 2 轮仍然是一轮完整的循环:Python 取出了 A002,也完成了状态判断。只是判断结果为 False,因此缩进在 if 下面的两行没有执行。随后循环正常进入第 3 轮。
这也解释了为什么累计器必须写在循环外:
total = 0.0
for order in orders:
total += order["amount"]
如果把 total = 0.0 放进循环体,每轮都会先归零,前一轮保存的累计结果就丢失了。
continue 和 break:一个跳当前轮,一个停整个循环
continue 与 break 都会改变正常的逐行顺序,但作用范围不同。下面的代码使用同一批订单,可以直接运行并对照输出:
orders = [
{"order_no": "A001", "status": "已支付", "amount": 129.0},
{"order_no": "A002", "status": "已退款", "amount": 88.0},
{"order_no": "A003", "status": "已支付", "amount": 199.0},
]
print("continue 的结果:")
for order in orders:
if order["status"] != "已支付":
continue
print(order["order_no"])
print("break 的结果:")
for order in orders:
if order["status"] == "已退款":
break
print(order["order_no"])
输出:
continue 的结果:
A001
A003
break 的结果:
A001
continue结束当前轮,回到循环顶部- 第 1 轮A001已支付 · 输出 A001
- 第 2 轮A002已退款 · 跳过本轮余下代码
- 第 3 轮A003已支付 · 继续输出 A003
- 结束列表用完循环正常完成
break结束整个循环,直接离开- 第 1 轮A001已支付 · 输出 A001
- 第 2 轮A002已退款 · 立即离开循环
- 未访问A003不会再开始第 3 轮
- 结束提前停止继续执行循环后面的代码
可以把差异压缩成一句话:
continue:这条数据不再处理,但下一条数据还要处理。break:已经找到停止条件,后面的数据全部不再处理。
筛掉取消订单通常适合 continue;查找第一条异常记录并立即停止时,break 更符合意图。不要仅因为两个关键字都能“跳过代码”就互换使用。
range 和 while 只在场景需要时使用
直接处理订单列表时,for order in orders 最容易读懂。需要明确重复固定次数时,可以使用 range():
for attempt in range(3):
print(f"第 {attempt + 1} 次尝试")
range(3) 依次给出 0、1、2,所以显示给人看的次数通常需要加 1。
当“是否继续”取决于一个条件,而不是一批现成数据时,可以使用 while:
attempt = 0
while attempt < 3:
print(f"第 {attempt + 1} 次尝试")
attempt += 1
while 每轮开始前都会重新检查条件。若忘记更新 attempt,条件会一直为 True,循环也就无法正常结束。对订单列表的日常遍历,优先使用更直接的 for。
动手练习:先预测,再运行
复制“筛选已支付订单并累计金额”的完整代码,按顺序完成:
- 不运行代码,先写出三轮的
order["order_no"]、is_paid、paid_count和total。 - 把 A002 的状态改成
"已支付",预测最终数量和金额,再运行确认。正确结果应是3和416.0。 - 在判断未支付后加入
continue,确认 A003 仍会被处理。 - 把同一位置改成
break,说明 A003 为什么不会被访问。 - 故意把
total = 0.0移进循环体,逐轮写出结果,解释累计为什么失效。
如果你能指出“当前是第几轮、order 指向谁、哪些行执行、累计器怎样变化”,就已经真正看懂了循环,而不只是会写 for。
循环让同一段代码处理多条数据;函数会让一段处理逻辑拥有清楚的输入、内部状态和返回结果。