系列 · Python 零基础到简单脚本 第 5 篇 / 共 11 篇 教程

Python 循环图解:看见每一轮发生了什么

用三条订单逐轮图解 for 循环:当前项怎样变化、条件是否命中、累计值如何更新,以及 continue 与 break 分别跳过了什么。

作者:黄撑 更新于 2026-08-27
本文目录 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 + 1total += order["amount"] 也是先用旧值完成加法,再把名字重新绑定到新结果。关键不是背写法,而是看见每轮的旧值和新值。

三次迭代 · 逐行轨迹每轮都从取出当前订单开始,再判断是否进入累计分支
第 1 轮当前项 · A001status: 已支付 · amount: 129.0
  1. 01 · 当前行for order in orders

    order → A001

  2. 02 · 当前行is_paid = order[“status”] == “已支付"

    "已支付” == “已支付” → True

  3. 03 · 条件if is_paid

    True · 选中,进入分支

  4. 04 · 数量paid_count += 1

    0 → 1

  5. 05 · 金额total += 129.0

    0.0 → 129.0

第 2 轮当前项 · A002status: 已退款 · amount: 88.0
  1. 01 · 当前行for order in orders

    order → A002

  2. 02 · 当前行is_paid = order[“status”] == “已支付"

    "已退款” == “已支付” → False

  3. 03 · 条件if is_paid

    False · 未选中,跳过分支

  4. 04 · 未执行paid_count += 1

    1 → 1 · 保持不变

  5. 05 · 未执行total += 88.0

    129.0 → 129.0 · 保持不变

第 3 轮当前项 · A003status: 已支付 · amount: 199.0
  1. 01 · 当前行for order in orders

    order → A003

  2. 02 · 当前行is_paid = order[“status”] == “已支付"

    "已支付” == “已支付” → True

  3. 03 · 条件if is_paid

    True · 选中,进入分支

  4. 04 · 数量paid_count += 1

    1 → 2

  5. 05 · 金额total += 199.0

    129.0 → 328.0

paid_count
  1. 开始0
  2. 第 1 轮1
  3. 第 2 轮1
  4. 第 3 轮2
total
  1. 开始0.0
  2. 第 1 轮129.0
  3. 第 2 轮129.0
  4. 第 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 放进循环体,每轮都会先归零,前一轮保存的累计结果就丢失了。

continuebreak:一个跳当前轮,一个停整个循环

continuebreak 都会改变正常的逐行顺序,但作用范围不同。下面的代码使用同一批订单,可以直接运行并对照输出:

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
路径对照遇到 A002 后,下一步去哪里
continue结束当前轮,回到循环顶部
  1. 第 1 轮A001已支付 · 输出 A001
  2. 第 2 轮A002已退款 · 跳过本轮余下代码
  3. 第 3 轮A003已支付 · 继续输出 A003
  4. 结束列表用完循环正常完成
break结束整个循环,直接离开
  1. 第 1 轮A001已支付 · 输出 A001
  2. 第 2 轮A002已退款 · 立即离开循环
  3. 未访问A003不会再开始第 3 轮
  4. 结束提前停止继续执行循环后面的代码

可以把差异压缩成一句话:

  • continue:这条数据不再处理,但下一条数据还要处理。
  • break:已经找到停止条件,后面的数据全部不再处理。

筛掉取消订单通常适合 continue;查找第一条异常记录并立即停止时,break 更符合意图。不要仅因为两个关键字都能“跳过代码”就互换使用。

rangewhile 只在场景需要时使用

直接处理订单列表时,for order in orders 最容易读懂。需要明确重复固定次数时,可以使用 range()

for attempt in range(3):
    print(f"第 {attempt + 1} 次尝试")

range(3) 依次给出 012,所以显示给人看的次数通常需要加 1。

当“是否继续”取决于一个条件,而不是一批现成数据时,可以使用 while

attempt = 0

while attempt < 3:
    print(f"第 {attempt + 1} 次尝试")
    attempt += 1

while 每轮开始前都会重新检查条件。若忘记更新 attempt,条件会一直为 True,循环也就无法正常结束。对订单列表的日常遍历,优先使用更直接的 for

动手练习:先预测,再运行

复制“筛选已支付订单并累计金额”的完整代码,按顺序完成:

  1. 不运行代码,先写出三轮的 order["order_no"]is_paidpaid_counttotal
  2. 把 A002 的状态改成 "已支付",预测最终数量和金额,再运行确认。正确结果应是 3416.0
  3. 在判断未支付后加入 continue,确认 A003 仍会被处理。
  4. 把同一位置改成 break,说明 A003 为什么不会被访问。
  5. 故意把 total = 0.0 移进循环体,逐轮写出结果,解释累计为什么失效。

如果你能指出“当前是第几轮、order 指向谁、哪些行执行、累计器怎样变化”,就已经真正看懂了循环,而不只是会写 for

下一篇函数:参数、局部变量与返回值

循环让同一段代码处理多条数据;函数会让一段处理逻辑拥有清楚的输入、内部状态和返回结果。