Python流程控制核心教程:if分支、for/while循环与实战技巧
前面两课我们把 Python 的变量、类型、运算符这些基础语法过了一遍已经能写一些从上往下执行的简单脚本了。但从这一课开始Python 才真正开始“有脑子”——流程控制就是给程序装上判断力和循环力的关键一课。你可以把它理解成给代码写“如果……就……否则……”的规则以及“重复做某件事 N 次”的复读机逻辑。无论你是零基础入门还是跟着教程学过一点但总是写不出自己的逻辑这一课的内容都能帮你把“看得懂代码”变成“写得出逻辑”。流程控制是编程语言的分水岭凡是牵扯到条件判断、循环遍历、分支选择的场景——比如登录验证、数据清洗、爬虫翻页、批量处理文件——背后全是它的影子。这一课的定位就是承上启下把 if、for、while、break、continue 这些关键字彻底讲清楚配合几个上手就能跑的练习让你在学完这一课后遇到实际问题时第一反应不是“怎么写”而是“我怎么用流程把这个问题拆开”。这篇内容我按从易到难的顺序来安排先讲分支判断再讲循环遍历然后用两个实战小项目把知识点串起来最后补充异常处理和避坑指南。每一段我都会把“为什么这么写”讲明白而不是只丢给你一堆语法。1. 流程控制的整体认知1.1 为什么说流程控制是编程的分水岭很多新手写代码前期靠的是“背语法”但到了流程控制这一课死记硬背就失灵了。因为流程控制要求你从“认识单词”过渡到“组织句子”程序不再是一条直线跑到黑而是根据不同的输入、不同的状态走不同的路。打个比方你点外卖的决策过程就是一套流程控制如果余额充足就下单否则就换一家或者放弃如果商家超时未接单就自动取消否则等待配送。每一步都是一个“条件判断”而取餐过程中反复查看配送进度就是一个“循环”。编程里的流程控制干的就是同样的事只不过决策者和执行者都是计算机而已。Python 的流程控制主要包含三块顺序结构、分支结构、循环结构。顺序结构你已经会了就是代码从上到下一行行执行分支结构用 if 系列关键字实现循环结构用 for 和 while 实现。这一课的重点就是后两块它们是程序逻辑复杂度的主要来源。1.2 学完这一课你应该掌握哪些东西我按实际的掌握程度给你列一个目标清单建议学完后对照自测能用 if、elif、else 组合出多条件分支并且不会把逻辑顺序搞乱。能用 for 循环遍历字符串、列表、range 序列知道循环变量在每一轮的值。能用 while 循环写出带退出条件的重复操作并避开死循环的坑。能用 break、continue 精确控制循环的“跳出”和“跳过”。能读懂循环嵌套并且自己写出类似九九乘法表这种经典练习。知道 try/except 能做基本的异常处理让程序在出错时不至于直接崩溃。如果你能达到这份清单的一半流程控制这一关就算过了如果全部达到你已经有能力解决很多日常脚本问题了。下面我们一项一项来。2. 条件分支 if/elif/else 的进阶用法2.1 最简单的 if 语句与缩进的“生死线”先看一个最基础的例子判断一个数是否为偶数number 10 if number % 2 0: print(这是一个偶数)这段代码的逻辑很直白如果 number 除以 2 的余数是 0就打印“这是一个偶数”。但新手最容易在“缩进”上栽跟头。Python 不像其他语言用大括号表示代码块它用缩进来表示。写在 if 下面且缩进了的代码才属于这个 if 的执行范围。注意同一个代码块内缩进必须保持一致。如果混用 Tab 和空格会让解释器直接报错IndentationError。我见过不少新手卡在这个问题上其实解法很简单——你的编辑器里统一把 Tab 键设置为“插入4个空格”以后就再也不会出现这种诡异错误了。if 语句后面一定要写冒号这个冒号是 Python 语法的一部分代表“接下来是条件成立时要执行的代码块”。忘了冒号同样会报语法错误。这种小细节说多了显得啰嗦但报错报多了你就知道九成新手 bug 都是这两类少了冒号、缩进不对。2.2 多条件判断elif 和 else 的配合顺序现实中的判断很少只有“是/否”两种情况。比如给成绩分等级90 分以上是 A80 到 89 是 B60 到 79 是 C60 以下是 D。这时候就需要 if、elif、else 全家桶score 85 if score 90: grade A elif score 80: grade B elif score 60: grade C else: grade D print(grade)这段代码的关键在于执行顺序。Python 会从上往下依次判断每个条件一旦遇到某个条件为 True就执行对应的代码块然后跳过整个 if-elif-else 结构不会再往下判断。所以条件的排列顺序非常重要。你把条件反过来写试试先写if score 60再写elif score 80结果 85 分也会被归到 C 档因为第一个条件就成立了。这就是“顺序决定结果”的典型例子。写多分支判断的时候建议把最严格、最特殊的条件放在最前面范围宽泛的放在后面这样逻辑才不会打架。还有一个新手经常搞混的地方是判断相等是赋值。if 条件里写if score 85会直接语法错误因为是赋值操作不是一个“比较”。这个错误不算隐蔽但我每次带新手都会强调一次——条件判断里永远用双等号。2.3 真值判断的“隐形规则”Python 里有个很贴心的特性不只是 True 和 False 可以作为判断条件很多对象也能直接放在 if 后面。比如数字 0、空字符串 、空列表 []、空字典 {}、None这些值在布尔上下文中都会被当作 False其他值则会被当作 True。这意味着你可以写出很简洁的判断name input(请输入你的名字) if name: print(f你好{name}) else: print(你好像什么都没输入。)这里没有显式写name ! 但效果一样。因为空字符串会被判断为 False非空字符串是 True。这种写法简洁且符合英文阅读习惯但我建议你刚开始学的时候还是写完整一点——if name ! ——让逻辑更直白。等你熟悉了真值判断的规则再改成简写也不迟。2.4 三目运算符与 match-case 的“现代写法”有时候你只是想根据条件选一个值不需要写一大段 if-else。比如根据分数判断“及格/不及格”用三目运算符可以压缩成一行result 及格 if score 60 else 不及格这个写法其实就是条件为真时取的值 if 条件 else 条件为假时取的值。它适合简单的二选一场景一旦分支变多还是老老实实用 if-elif-else 更好否则一行代码长得像绕口令别人读起来费劲。如果你用的是 Python 3.10 以上版本还可以试试 match-case 语句它类似其他语言里的 switch适合做多值匹配。比如根据用户输入的命令执行不同操作command input(请输入命令) match command: case start: print(开始运行) case stop: print(停止运行) case _: print(未知命令)最后的case _相当于 else匹配所有未列出的情况。这个语法挺时髦但第三课阶段了解一下即可实际项目中时常用 if 也能实现同样的效果。3. for 循环和 while 循环怎么选3.1 for 循环的本质遍历迭代器for 循环是 Python 里最常用的循环它的本质是“遍历一个可迭代对象”。字符串、列表、元组、字典、range 序列都是可迭代对象你都可以用 for 把它们里面的元素一个一个取出来。fruits [苹果, 香蕉, 橙子] for fruit in fruits: print(fruit)这段代码做的事情很直观第一次循环时 fruit 等于“苹果”第二次等于“香蕉”第三次等于“橙子”。循环体执行几次取决于列表里有几个元素。for 循环的优点是你不用自己维护“循环次数”这个变量Python 自动帮你迭代完整个序列。实际工作中最常见的 for 循环场景是和 range 函数配合生成一个数字序列for i in range(5): print(i)range(5) 生成的是 0 到 4 这五个数字注意不包含 5。这是编程里一个非常经典的“从 0 开始”习惯新手刚接触时经常算错边界。你可以用 range(1, 6) 显式指定从 1 开始到 5 结束第三个参数还可以控制步长比如 range(0, 10, 2) 生成 0、2、4、6、8。排查建议如果你的循环结果里“少了一个数”或者“多了一个数”先检查 range 的起止边界。range 的区间是左闭右开也就是包含起始值、不包含结束值。记住这一条能省不少调试时间。3.2 while 循环的使用场景与死循环避坑while 循环和 for 循环最大的区别在于for 明确知道要循环多少次而 while 是“只要条件成立就一直循环”。什么时候用 while 更合适典型场景是你不知道循环什么时候结束——比如用户输入的密码直到正确为止、游戏角色血量降到 0 为止。password while password ! python123: password input(请输入密码) print(密码正确进入系统)这段代码会一直要求用户输入直到输入的字符串等于“python123”才退出循环。这里有一个新手必踩的坑while 循环的条件判断中一定要有某个变量在循环体内被改变否则条件永远成立程序就成了死循环。我见过一个很经典的死循环i 1 while i 5: print(i) # 忘记写 i 1这段代码会一直打印 1因为 i 永远不增加条件i 5永远为 True。遇到这种情况终端会疯狂刷屏你只能按 CtrlC 强制终止程序。写 while 循环时养成一个好习惯先问自己“循环体内哪一行代码负责让条件最终变成 False”如果答不上来大概率就会写出死循环。3.3 break、continue、else 的搭配规则循环只有“跑完”和“跑不完”两种状态但有时候你想在中间干预一下。break 和 continue 就是干这个的break 是提前退出整个循环continue 是跳过当前这一轮、直接进入下一轮。for i in range(1, 10): if i 3: continue if i 7: break print(i)这段代码会打印 1、2、4、5、6然后当 i 等于 7 时触发 break循环彻底结束。注意 continue 跳过了 i 等于 3 的那一轮所以 3 没有打印出来。区分这两个关键字有一个通俗的记忆方法break 是“破门而出”continue 是“跳过这一关继续前进”。Python 的循环还有一个很少人知道但很实用的特性——循环还可以带 else。这个 else 不是和 if 搭配的那个 else它表示“循环正常结束后执行一次”。如果循环被 break 打断了else 就不会执行。numbers [1, 3, 5, 7, 9] for n in numbers: if n % 2 0: print(找到了偶数, n) break else: print(列表里没有偶数)这个特性特别适合“找东西”的场景比如在一组数据里搜索符合条件的元素找到了就 break 退出没找到就执行 else 里的提示逻辑。很多其他语言没有这个语法所以如果你是别的语言转过来的可能会觉得有点新鲜。建议刻意用几次就能体会到它的简洁。4. 实战练习从“看懂”到“写出来”4.1 经典案例猜数字小游戏说一千道一万不如动手写一段完整的程序。我首选推荐猜数字游戏因为它能同时锻炼 if、while、break、随机数、类型转换等知识点。规则很简单程序随机生成一个 1 到 100 的整数用户输入数字猜测程序提示“大了”“小了”或“猜对了”。import random target random.randint(1, 100) count 0 while True: guess input(请输入你猜的数字1-100) if not guess.isdigit(): print(请输入一个有效的整数。) continue guess int(guess) count 1 if guess target: print(大了再猜小一点。) elif guess target: print(小了再猜大一点。) else: print(f恭喜你猜对了你一共猜了 {count} 次。) break这段代码有几个值得注意的细节。第一input返回的是字符串必须用int()转成整数才能和 target 比较。第二用户可能输入非数字所以用isdigit()先做合法性校验不合法就 continue 跳过这一轮。第三while True 配合 break 是“先进入循环再判断是否退出”的经典写法非常适合人机交互场景。这个游戏你也可以扩展一下增加最大猜测次数超过次数提示失败加入难度选择简单模式 1-50、困难模式 1-1000记录历史最佳成绩。每扩展一个功能你就相当于多练了一次流程控制的组合运用。4.2 经典案例九九乘法表与循环嵌套九九乘法表是练习嵌套循环的经典题目。嵌套循环就是循环里面套循环外层循环每执行一轮内层循环会完整执行一遍。打印九九乘法表的逻辑是外层循环负责行数1 到 9内层循环负责每行打印几个式子。for i in range(1, 10): for j in range(1, i 1): print(f{j} × {i} {i * j}, end\t) print()注意内层循环的 range 是range(1, i 1)也就是说第 i 行只打印 i 个式子。这样第 1 行只有一个“1×11”第 9 行有九个式子。end\t表示打印完不换行而是以制表符结尾这样同一行的几个式子能并排显示内层循环结束后再调用一个空的print()换行。运行效果大概是1 × 1 1 1 × 2 2 2 × 2 4 1 × 3 3 2 × 3 6 3 × 3 9嵌套循环的核心是把“循环变量”之间的关系理清楚。外层变量 i 控制行数内层变量 j 控制列数第 i 行第 j 列的值就是j × i。如果你用代码打印一个矩形或三角形图案思路也是完全一致的。新手第一次接触嵌套循环容易晕建议拿笔在纸上画几行推导一下把 i 和 j 的值写出来比空想快得多。4.3 综合小练习判断一个数是不是素数如果你觉得九九乘法表太简单可以尝试写一个“判断素数”的功能。素数就是只能被 1 和自身整除的大于 1 的自然数比如 2、3、5、7、11。判断一个数 n 是不是素数只需要从 2 试到 n 的平方根看有没有能整除它的数。import math n int(input(请输入一个大于1的整数)) is_prime True if n 1: is_prime False else: for i in range(2, int(math.sqrt(n)) 1): if n % i 0: is_prime False break if is_prime: print(f{n} 是素数) else: print(f{n} 不是素数)这里用到了 for-else 的逻辑变体如果循环过程中找到了因子break 退出is_prime 被设为 False如果循环正常结束说明没有因子能够整除 nis_prime 保持 True。当然显式使用一个布尔变量来控制状态对新手来说更直观理解起来压力更小。你可能会问为什么只需判断到sqrt(n)就够了因为如果 n 有一个大于平方根的因子 a那么必然存在一个小于平方根的小因子 b使得 a×bn。也就是说只要检查到平方根位置都没找到因子再往上检查也是多余的。这个思路在算法优化里很常见——通过数学性质缩小搜索范围避免不必要的循环消耗。5. 异常处理与逻辑简化的小技巧5.1 try/except 让程序“优雅地出错”第三课虽然主要讲流程控制但我强烈建议你把 try/except 这一课提前学掉。原因是你在实操中一定会遇到用户乱输入、文件不存在、网络超时这些情况如果没做异常处理程序直接崩溃退出体验很差。异常处理的本质也是流程控制——正常流程怎么走出错流程怎么走。看一个例子把字符串转成整数用户如果输入“abc”就会抛 ValueErrorwhile True: text input(请输入一个整数) try: number int(text) break except ValueError: print(这不是一个整数请重新输入。)这个写法比前面用的isdigit()更通用因为有些字符串isdigit()判断为 True但int()照样可能失败。try 块里的代码是“冒险操作”如果抛出异常程序不会崩溃而是跳到 except 块执行对应处理如果没异常就跳过 except 继续往下走。对于入门阶段你只需要掌握这一个模式就够用了。经常有人问 try/except 和 if 判断哪个更好。我的经验是能提前用 if 判断的先用 if 避免异常无法提前预判的错误比如文件被占用、网络断连再用 try/except 兜底。两者不是替代关系而是互补关系。5.2 列表推导式用一行代码替换简单循环列表推导式是一个非常“Pythonic”的写法它把 for 循环和列表创建合并成一行表达式。比如生成 1 到 10 的所有偶数平方squares [i * i for i in range(1, 11) if i % 2 0] print(squares)这个式子等价于squares [] for i in range(1, 11): if i % 2 0: squares.append(i * i)列表推导式的语法结构是[表达式 for 变量 in 可迭代对象 if 条件]if 部分可以省略。我建议你在完全掌握普通 for 循环之后再接触这个写法因为列表推导式虽然简洁但对新手来说可读性差一个复杂的推导式能让你半天看不懂。实际开发中我一般只在逻辑简单的时候用它复杂逻辑还是老老实实写普通循环。5.3 enumerate 与 zip让循环更顺手遍历列表时很多时候你既需要元素值又需要元素下标。用最原始的方式写你需要引入一个计数器变量fruits [苹果, 香蕉, 橙子] index 0 for fruit in fruits: print(index, fruit) index 1有了 enumerate这个操作就优雅多了for index, fruit in enumerate(fruits): print(index, fruit)enumerate 会返回一个包含“下标”和“值”的二元组用两个变量同时接收即可。还有一种常见场景是同时遍历两个列表比如把学生姓名和分数一一对应names [张三, 李四, 王五] scores [90, 85, 78] for name, score in zip(names, scores): print(f{name} 的分数是 {score})这两组工具函数能减少你写循环时的样板代码让逻辑更清晰。它们也是 Python 开发者日常使用频率非常高的内置函数建议这一课就直接记住。6. 常见问题与排查技巧实录6.1 死循环的快速定位与处理死循环大概是流程控制阶段最让人抓狂的问题。如果程序在终端里一直刷输出、没有任何停止迹象大概率就是 while 循环的条件永远为真或者 for 循环的遍历对象本身有问题。排查死循环我有一套固定流程。第一步先按 CtrlC 强制终止程序观察报错信息里停在哪个文件哪一行那里往往就是循环体内部。第二步检查 while 循环的条件变量是否在循环体内部被更新如果有 break 语句检查 break 前面是否满足了合适的条件。第三步在循环体里临时加几个 print把关键变量的值打印出来看它是否朝着预期的方向变化。定位到是哪一行导致条件一直为真修复方案也就自然出来了。6.2 缩进错误与逻辑错误的区分缩进错误IndentationError是最容易排查的错误Python 编译器会直接告诉你“expected an indented block”或者“unexpected indent”看着报错提示就能找到问题。真正的难点是逻辑错误——程序不报错但结果就是不对。我举一个最常见的逻辑错误场景判断年份是否为闰年。正确的规则是“能被 4 整除但不能被 100 整除或者能被 400 整除”新手很容易漏掉“不能被 100 整除”这个条件导致 1900 年这种年份被误判。这类错误编译器不会发现只有测试用例才能暴露。所以写完代码之后一定要准备多组边界数据自测比如最小的输入值、最大的输入值、临界值等。流程控制写的不是“让程序跑起来”而是“让程序在每一种情况下都跑对”。6.3 变量作用域与循环变量的“残留”问题Python 的 for 循环变量有一个特性循环结束后循环变量仍然存在值等于最后一次循环的值。这个和某些其他语言不一样容易带来隐藏 bug。比如for i in range(5): pass print(i) # 输出 4i 仍然存在这个问题的典型场景是循环次数为 0 时循环变量根本不会被赋值后面再用它就会报 NameError。所以不要依赖循环之后循环变量的值如果需要保留结果就在循环之前初始化一个变量。while 循环类似如果循环的条件判断依赖某个外部变量而这个变量没有被正确初始化程序可能直接跳过循环体或者一进来就满足退出条件。不管是哪种循环写完多问一句如果循环一次都没执行程序会怎样这个习惯能帮你避免很多条件边界的坑。6.4 关于流程控制的最后一点心得我自己带新手学 Python 的时候发现流程控制这一课最容易出现两个极端一类同学觉得太简单看一遍就跳过结果遇到实际问题不知道用哪种循环另一类同学陷入语法细节总想找一个“万能模板”但逻辑一变就懵了。其实流程控制的核心不在语法而在于“把问题拆成顺序、分支、循环三种结构”的能力。你可以试着用这个方法来训练自己拿到一个实际问题先不写代码用大白话把流程说一遍比如“先判断输入是否合法如果合法就计算否则提示错误计算的结果放进列表里一直算到达到目标数量为止”。流程说清楚了翻译成 Python 只是时间问题。写代码卡住的时候不妨停下来把逻辑重新讲一遍往往讲着讲着问题就自己暴露了。流程控制练熟之后你会发现自己已经能读懂不少实用的脚本了。下一步可以尝试写一些解决实际小事的程序比如批量重命名文件、定时提醒、验证码生成器这些项目会在后面的课程里一一展开但它们的底子都是这一课的分支与循环。最后分享一个我自己的习惯每写一个循环都问自己一句——这个程序有没有可能在某个输入下永远退出不了这个习惯帮我挡掉过无数次生产事故希望你也能用上。