4. 分支与循环控制语句归纳总结
控制流是编程的骨架。分支和循环,说白了就是让代码能“做选择”和“重复干活”。我做了这么多年批处理脚本,发现很多人把这两块搞混,要么到处用if套if,要么滥用while死循环。这一章咱们把分支和循环彻底捋清楚,再结合MD质控的实际场景,给出一个趁手的兵器谱。
4.1 分支语句:if/elif/else
分支就是给程序装个脑子。if判断条件,满足就走一块,不满足就走另一块。Python的写法很简洁,不用花括号,靠缩进控制块。
qc_pass = True
if qc_pass:
print("质控通过,继续")
else:
print("质控失败,标记")
我在项目里见过有人写七八个elif,那个可读性……后来我统一用字典映射或者策略模式代替。建议:elif不超过三层,否则改用数据结构查表。
还有个坑:条件顺序。我曾经把一个宽范围的条件写在前面,结果后面的细粒度分支永远走不到。代码里一定要把最具体、最匹配的判断放最前。
4.2 循环语句:for 与 while
循环就是重复干活。for适合明确迭代次数的场景,while适合条件驱动的场景。下面这张表是我个人的选择习惯:
| 维度 | for | while |
|---|---|---|
| 适用场景 | 遍历列表、文件行、固定范围 | 状态等待、用户输入重试 |
| 代码简洁性 | 高,自带迭代器 | 低,需手动维护计数器 |
| 风险 | 不易死循环 | 容易忘记更新条件导致死循环 |
| 实战推荐 | 90%的批处理循环 | 仅用于不确定次数的等待 |
举个例子,批量读取MD文件:
mds = ["sample1.md", "sample2.md", "sample3.md"]
for md in mds:
process(md) # 逐文件质控
而while一般用在“直到满足条件”的地方,比如等外部状态文件生成:
import time
while not os.path.exists("qc_done.flag"):
time.sleep(5)
print("等待质控完成...")
我个人习惯:能用for绝不写while,少一个计数器就少一个bug。
4.3 循环控制:break、continue、pass
这三个小工具很实用,但也容易用错。说说我的理解:
- break:立刻跳出整个循环。我在处理质控异常时常用——一旦发现某个样本严重失败,直接终止当前批次后续处理。
- continue:跳过本次循环剩余语句,进入下一次。适合“跳过不合格样本,继续处理下一个”。
- pass:啥也不做,占位用。我一般只在写未实现的分支时临时放一个,上线前必须删掉。
警告:break和continue在嵌套循环里只作用于最内层。我曾经忘了这点,在两层for里面用break想跳出外层,结果逻辑全乱了。后来改用函数返回或者异常处理。
for batch in batches:
for sample in batch:
if sample.failed_critical:
break # 只跳出内层for
else:
continue # 内层没break才执行
break # 内层break后跳出外层
嗯,这个“for-else”结构很多新手不知道。其实它特别适合“遍历查找,找到就跳出”的模式。
4.4 实战:质控流程中的控制流
把上面讲的串起来,做一个完整的质控流水线。流程是这样的:
- 遍历所有待处理文件(for)
- 检查文件格式是否合规(if/else)
- 如果格式错误,跳过该文件(continue)
- 执行内容校验,失败次数累计(while? 不,这里我用for + 固定重试次数)
- 如果致命错误,立即终止整个批次(break + 外层标记)
- 否则记录结果,继续下一个
代码示例:
qc_failed = False
for filename in file_list:
if not is_valid_format(filename):
print(f"跳过{filename}:格式错误")
continue
retry = 3
for attempt in range(retry):
result = run_qc(filename)
if result.passed:
break
print(f"第{attempt+1}次尝试失败")
else:
qc_failed = True
break # 重试全部失败,终止批次
if qc_failed:
print("批次质控终止")
else:
print("批次全部通过")
你看,一个for嵌套就解决了重试和终止,没有用while。这种模式我用了好多年,稳定可靠。
4.5 知识图谱:控制流全貌
下面这张图概括了本章所有控制结构的关系。注意:顺序流是隐含的基础,分支和循环在顺序流上搭建,而break/continue是循环内部的“刹车和跳板”。
小技巧:设计控制流时,先画草图(就像上面的SVG),再写代码。我每次设计新的批处理逻辑,都会先在纸上画个流程,能避免很多“else挂错if”的尴尬。
注意:Python的for-else和while-else结构容易让人困惑。记住:else只在循环正常结束(没有被break打断)时执行。调试时可以在else块里加个日志,确认循环是否提前终止。