上一篇 循环语句 for 与 while 讲了 for/while 的基础,但真实项目里的循环往往需要动态控制——“某个条件满足时立刻退出”、”这一轮跳过不处理”、”循环正常结束后跑一段收尾”。这就是 break / continue / else 三件套的用武之地。这一篇把它们的语法、语义、惯用法、陷阱一次讲清,特别是 for-else 这个 Python 独有的语法糖,被无数新手忽视,其实很好用。
一、break:立刻退出循环
break 中断最近一层的循环,控制流跳到循环体后的第一条语句:
1 | # 找出第一个负数 |
break 只跳最近一层,嵌套循环里想跳到最外层需要额外手段(下面讲)。
二、continue:跳过本次迭代
continue 结束本次迭代,直接进入下一轮循环开头(for 会取下一个元素,while 会重新判断条件):
1 | # 只打印偶数 |
注意:continue 不是 break 的近亲,它不会退出循环,只是跳过剩余的循环体。
continue 与 else if 的区别
1 | # 用 continue(Guard 式) |
两种写法功能等价,但当验证逻辑很多时(比如 5 层校验),continue 让代码扁平化:
1 | for order in orders: |
比嵌套 4 层 if 好读得多。
三、else:循环正常结束后的收尾
for-else 和 while-else 是 Python 特色:当循环因为”迭代完成”而结束(没被 break 打断)时,执行 else 块。
1 | for n in [3, 5, 7, 11]: |
理解要点:else 不是配 if 的,是配 for/while 的。语义可以读成”loop nobreak”—— 循环没被打断时才执行。
常见惯用法:搜索”是否存在”
1 | def find(items, target): |
for-else 让”未找到”分支非常自然。不用它就得:
1 | found = False |
多一个 flag 变量,明显啰嗦。
while-else
while 也支持 else:条件变为假时执行 else(等同”没被 break”)。
1 | attempts = 0 |
四、跳出嵌套循环的四种姿势
break 只跳一层。想跳多层,四种方案:
方案 1:抽成函数 + return(推荐)
1 | def find(matrix, target): |
这是最 Pythonic 的做法。别的方案都是它的降级替代。
方案 2:flag 变量
1 | found = False |
多层 flag 会越写越乱,慎用。
方案 3:抛异常
1 | class _Found(Exception): |
用异常做流控被认为是反模式,除非嵌套非常深,否则不建议。
方案 4:把嵌套改成扁平
用 itertools.product 或者展开成单层:
1 | from itertools import product |
五、continue 在 while 里的坑
在 while 里用 continue 时,别忘了更新循环变量,否则死循环:
1 | i = 0 |
正确写法:
1 | i = 0 |
for 循环用 continue 就没这个坑,因为迭代器自动”下一步”。所以能用 for 就别用 while。
六、for-else 到底该不该用?
有人觉得 for-else 让代码更简洁,也有人(包括 Guido 本人)承认这个关键字选得不好——else 语义不直观。原本更贴切的名字是 nobreak。用不用这个语法,业界有两派:
- 鼓励派:写搜索/检查场景时优雅,减少 flag 变量;
- 保守派:容易被误读为”if-else 的 else”,代码 review 时增加认知负担。
折中建议:
- 团队里所有人都懂 → 大胆用;
- 有人不熟 → 加一行注释
# 循环没 break; - 或者干脆抽成函数,用 return 表达”提前找到”。
七、一个综合例子:账户登录
1 | # login.py |
这段代码里同时用了 break(退出命令循环)、continue(跳过空行/错误用户名)、for-else(三次失败后锁定)、return(登录成功直接跳出函数)。
八、常见陷阱
陷阱 1:break 与 return 混用
在函数里,能用 return 就用 return,比 break 更”干脆”:
1 | def find(items, target): |
陷阱 2:for-else 里没 break
1 | for x in items: |
如果循环里没有 break,else 块是必然执行的,等价于把它写在循环后面——但读代码的人会疑惑”为啥用 else”。没 break 就别写 else。
陷阱 3:continue 后写代码
1 | for x in items: |
continue 后面的代码是死代码,多数 linter 会警告。
陷阱 4:break 跳不出嵌套函数
1 | def outer(): |
break 只在当前函数的最近一层循环生效。
陷阱 5:while True 忘了退出条件
1 | while True: |
while True 一定要有 break 或 return 或 raise,否则就是死循环。
九、性能小提示
- 循环开销:CPython 里循环开销比 C 大得多,能用内置函数就别自己写循环:
- 累加:
sum(nums)比for + +=快; - 找最大:
max(nums); - 存在性:
any(x > 0 for x in nums)、all(x > 0 for x in nums); - 一次性构造 list:列表推导式比 append 循环快 30%+。
- 累加:
break早退能避免不必要的工作,尤其是数据量大时。
十、小结与延伸阅读
break退出最近一层循环;continue跳过本次迭代;else在循环没被 break 时执行;- 嵌套循环退出优先用函数 + return;
while + continue记得手动更新循环变量;- 没 break 别写 else;
- 能用 sum/max/any/all/推导式就别写手工循环。
延伸阅读:
- Python 官方 break/continue 文档:https://docs.python.org/zh-cn/3/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops
- Fluent Python(书)中关于 for-else 的详细讨论。
到这里 模块一:Python 基础入门 10 篇 就全部结束了!从下一篇开始进入 模块二:核心数据结构,第一站是 列表 List 详解。