循环是编程里最容易被低估的一块内容。刚学Python那会儿我觉得for和while不就是转圈圈嘛能有多难结果真正写起业务逻辑来才发现坑全在细节里什么时候该用while、什么时候用for、死循环怎么救、break和continue到底跳哪一层、嵌套循环里变量怎么不串味……这些问题不搞清楚写出来的代码要么跑飞要么逻辑错乱。这篇笔记就是把我自己在学Python循环这一块踩过的坑、总结的方法、以及反复验证过的实操案例完整梳理一遍。不管你是刚接触编程的新手还是想回头把基础打牢的开发者这篇内容都能让你对Python循环有一个从会用到用对的认知升级。核心关键词Python循环、while循环、break、continue、循环嵌套、九九乘法表、死循环、计数方法。1. 程序的三大流程与循环的定位1.1 顺序、分支、循环到底在解决什么问题任何一段程序拆到最底层无非就是三种执行结构在排列组合顺序结构、分支结构、循环结构。这个说法听起来像教科书但我实际写代码之后发现用这个框架去拆解需求特别高效。顺序结构就是代码从上往下一行行执行没有任何拐弯。比如你定义变量、做一次计算、打印一个结果这些都是顺序执行。它是最基础的但能解决的问题也最有限——因为真实需求几乎都带有条件判断和重复操作。分支结构解决的是不同情况走不同路的问题。if、elif、else就是干这个的。用户输入了A就做这件事输入了B就做那件事。分支让程序有了选择能力。循环结构解决的是同一件事做很多遍的问题。这是三大流程里最能体现计算机价值的一环——人做重复劳动会累会出错计算机不会。循环就是把这个重复抽象出来让代码写一遍就能跑一万遍。我个人的理解是顺序是骨架分支是神经循环是肌肉。三者配合才能撑起一个完整的程序逻辑。而循环往往是初学者最容易写错、也最能拉开水平差距的部分。1.2 为什么循环是新手的分水岭我观察过身边学Python的人发现一个规律能熟练用好循环的人后面学函数、学数据处理、学爬虫都顺风顺水循环没搞明白的人后面几乎处处卡壳。原因很简单——循环是第一个需要你在脑子里模拟程序运行过程的知识点。顺序结构你一眼能看完分支结构你画个流程图也能理清但循环不一样它涉及变量的反复变化、条件的反复判断、执行路径的反复跳转。你必须在脑子里或者纸上把这个过程跑一遍才能确认逻辑对不对。而且循环直接关联到后面大量的实战场景遍历列表、处理文件每一行、批量请求接口、生成报表数据……这些全都是循环的变体。循环没打牢后面全是空中楼阁。所以我的建议是循环这一块不要急着往下学多写、多调试、多画执行过程把每一种写法都亲手跑一遍直到你能闭着眼睛说出这段代码执行时变量是怎么变的。2. while循环的基本使用与执行逻辑2.1 while循环的语法结构与执行流程while循环的语法非常简洁while 条件表达式: 循环体代码执行逻辑是这样的先判断条件表达式如果为True就执行循环体执行完循环体后再回到条件表达式重新判断如果为False就跳出循环执行循环后面的代码。我用一个最朴素的例子来演示count 1 while count 5: print(f当前数字是{count}) count 1 print(循环结束)这段代码的执行过程我建议你在纸上一行行模拟count初始为1判断1 5为True打印当前数字是1count变成2判断2 5为True打印当前数字是2count变成3……以此类推当count变成6时判断6 5为False跳出循环打印循环结束最终输出1到5然后输出循环结束。这个手动模拟的过程是理解循环最有效的方法没有之一。2.2 循环变量的初始化与更新为什么缺一不可新手写while循环最常犯的错误就是忘记更新循环变量或者初始化位置放错。这两个问题都会直接导致死循环。循环变量必须满足两个条件第一在循环开始之前初始化第二在循环体内部被更新。缺了第一个程序会报NameError缺了第二个条件永远为True程序就卡死了。# 错误示范忘记更新 i 1 while i 5: print(i) # 这里忘了写 i 1i永远是1条件永远为True # 正确示范 i 1 while i 5: print(i) i 1我踩过的一个坑是把i 1写在了if分支里面结果某些情况下分支没进去i就没更新循环直接卡死。所以更新循环变量的语句最好放在循环体的主干路径上不要藏在条件分支里除非你非常确定每条路径都会更新它。提示写while循环时先问自己两个问题——循环变量在哪里初始化在哪里更新这两个问题答不上来代码大概率有问题。2.3 while循环适合什么场景while循环最适合的场景是循环次数不确定只知道什么时候该停。比如让用户不断输入直到输入quit为止不断生成随机数直到满足某个条件读取数据流直到读到结尾这类场景用for循环反而别扭因为for需要一个明确的迭代对象。而while只需要一个条件条件满足就继续不满足就停非常灵活。反过来如果你明确知道要循环多少次或者要遍历一个列表、字符串、range对象那用for更合适。这不是硬性规定但遵循这个习惯能让代码更清晰。3. 死循环的成因、利用与逃生方法3.1 死循环是怎么产生的死循环就是条件永远为True循环永远不退出。产生的原因通常有三类第一类循环变量忘记更新。这是最常见的前面已经说过。第二类条件表达式写错。比如本该写i 10结果写成了i 10方向反了条件一开始就不满足或者永远满足。第三类循环体内部有逻辑导致变量不按预期变化。比如变量在某个分支里被重置了或者被其他代码意外修改。# 典型死循环 i 0 while i 10: print(i) # 忘记 i 1 # 条件写反 i 0 while i -1: # 这个条件永远为True只要i不变成负数 print(i) i 13.2 死循环不一定是bug有时是设计这一点很多人一开始不理解。死循环在某些场景下是有意为之的比如服务器的主循环需要一直运行监听请求游戏的主循环需要一直刷新画面和处理输入交互式程序的输入循环需要一直等待用户操作这些场景下程序本来就应该永远运行直到外部强制停止或者满足某个退出条件通常配合break使用。# 有意的死循环配合break退出 while True: user_input input(请输入内容输入quit退出) if user_input quit: break print(f你输入了{user_input})这种while True加break的写法在实际开发中非常常见因为它把退出条件放在了循环体内部逻辑更清晰。3.3 不小心写出死循环怎么救如果你在命令行里跑出了一个死循环程序卡住不动了怎么办最直接的方法是按Ctrl C发送中断信号强制终止程序。这是最常用的逃生手段。如果你用的是IDE通常有一个红色的停止按钮点一下就能终止运行。如果是在Jupyter Notebook里点工具栏上的停止按钮方块图标或者重启内核。注意死循环本身不会损坏电脑它只是占着CPU不放。但如果你在死循环里不断往列表里追加数据内存会被吃光那就可能拖慢整个系统。所以发现死循环要尽快终止。我个人的习惯是写while循环时先在脑子里过一遍这个循环有没有可能永远不退出如果有可能就加一个最大迭代次数作为保险max_iter 1000 i 0 while i 10: # 业务逻辑 i 1 max_iter - 1 if max_iter 0: print(达到最大迭代次数强制退出) break这个技巧在调试阶段特别有用能防止程序卡死。4. 计数方法与循环计算的实战套路4.1 计数器模式循环里最常见的套路计数器是循环里最基础也最常用的模式。核心思路是在循环外面定义一个变量初始为0循环里每满足一次条件就加1。# 统计1到100里有多少个偶数 count 0 i 1 while i 100: if i % 2 0: count 1 i 1 print(f1到100里共有{count}个偶数)这个模式的变化非常多统计满足条件的元素个数、统计字符串里某个字符出现的次数、统计用户输入了多少次……本质都是一样的。我踩过的一个坑是把计数器变量和循环变量搞混了。比如用i既当循环变量又当计数器结果逻辑一团乱。我的建议是循环变量和计数器变量分开命名循环变量用i、j、k计数器用count、total、num一眼就能区分。4.2 累加与累乘循环计算的两种基本形态累加和累乘是循环计算的两大基本形态。累加的模式是定义一个初始值为0的变量循环里不断往上面加。# 计算1到100的和 total 0 i 1 while i 100: total i i 1 print(f1到100的和是{total})累乘的模式是定义一个初始值为1的变量注意不是0循环里不断往上乘。# 计算5的阶乘 result 1 i 1 while i 5: result * i i 1 print(f5的阶乘是{result})这里有个关键细节累乘的初始值必须是1不能是0。因为0乘任何数都是0结果永远是0。这个坑我见过太多人踩了。4.3 循环里的变量作用域与命名建议Python没有块级作用域循环里定义的变量在循环外面也能访问。这既是便利也是陷阱。i 0 while i 3: temp i * 2 i 1 print(temp) # 输出4temp在循环外依然可访问这个特性意味着如果你在循环里用了某个变量名循环外面又用了同名变量可能会互相干扰。我的建议是循环变量用简短的名字i、j、k临时变量用有意义的名字temp、current、item累加器、计数器用明确的名字total、count、sum_result避免在循环内外复用同一个变量名做不同的事提示虽然Python允许循环变量在循环外访问但循环结束后循环变量的值是最后一次更新后的值不要依赖这个值做逻辑判断容易出错。5. break与continue的正确使用姿势5.1 break彻底跳出当前循环break的作用是立即终止当前所在的循环跳到循环后面的代码继续执行。i 1 while i 10: if i 5: break print(i) i 1 print(循环结束)这段代码只会打印1、2、3、4当i等于5时遇到break直接跳出循环打印循环结束。break最常用的场景是在循环里找到了想要的结果不需要继续找了直接退出。# 在列表里找第一个大于100的数 numbers [12, 45, 78, 120, 33, 200] i 0 while i len(numbers): if numbers[i] 100: print(f找到第一个大于100的数{numbers[i]}) break i 15.2 continue跳过本次继续下一次continue的作用是跳过当前这一次循环的剩余代码直接进入下一次循环的条件判断。i 1 while i 10: if i 5: i 1 continue print(i) i 1这段代码会打印1、2、3、4、6、7、8、9、10唯独跳过了5。这里有个大坑在while循环里用continue一定要确保循环变量在continue之前被更新否则会死循环。# 错误示范continue之前没更新i i 1 while i 10: if i 5: continue # i永远是5死循环 print(i) i 1这个坑我踩过不止一次特别是在逻辑复杂的时候continue一加循环变量更新语句就被跳过了。所以我的习惯是在while循环里用continue先把循环变量更新语句放在continue之前或者干脆改用for循环。5.3 break和continue的对比与选择特性breakcontinue作用终止整个循环跳过本次循环剩余代码执行后循环结束执行循环后面的代码回到条件判断继续下一次循环常用场景找到目标后提前退出跳过不符合条件的元素在嵌套循环中只跳出当前这一层只影响当前这一层选择原则很简单如果你要不干了彻底退出用break如果你要这次不算下一个用continue。我个人的经验是continue用多了会让代码逻辑变得难以追踪因为它跳过了循环体的一部分。如果循环体逻辑比较复杂我倾向于用if-else把逻辑写完整而不是用continue跳过。这样代码更直观调试也更容易。6. 循环嵌套的原理与打印小星星实战6.1 嵌套循环的执行顺序循环嵌套就是循环里面还有循环。外层循环每执行一次内层循环完整执行一遍。i 1 while i 3: j 1 while j 3: print(fi{i}, j{j}) j 1 i 1执行顺序是i1进入内层j从1到3打印三行i2进入内层j从1到3打印三行i3进入内层j从1到3打印三行总共打印9行。理解这个执行顺序是写好嵌套循环的关键。我建议在纸上画一个表格行是外层变量列是内层变量把每一次执行都填进去这样一眼就能看出执行了多少次、变量怎么变的。6.2 打印小星星嵌套循环的经典入门案例打印小星星是嵌套循环最经典的练习没有之一。它的变体非常多从简单的矩形到三角形、倒三角形、菱形每一种都在考察你对嵌套循环的理解。先看最简单的矩形# 打印5行5列的星星 i 1 while i 5: j 1 while j 5: print(*, end) j 1 print() # 换行 i 1输出***** ***** ***** ***** *****这里的关键是print(*, end)end参数设为空字符串表示打印后不换行。内层循环结束后用一个空的print()来换行。再看三角形# 打印5行递增的三角形 i 1 while i 5: j 1 while j i: print(*, end) j 1 print() i 1输出* ** *** **** *****这里内层循环的条件是j ii越大内层循环次数越多星星就越多。倒三角形i 5 while i 1: j 1 while j i: print(*, end) j 1 print() i - 1输出***** **** *** ** *6.3 嵌套循环的变量命名与调试技巧嵌套循环最容易出的问题是变量串味。比如内层循环用了和外层一样的变量名或者内层循环结束后变量值没重置。我的建议是外层循环变量用i内层用j再内层用k形成习惯内层循环的变量必须在进入内层之前初始化不能依赖上一次的值每次内层循环结束后检查是否需要重置内层变量调试嵌套循环时我常用的方法是在循环里加打印语句把每一层的变量值都打出来i 1 while i 3: j 1 while j 3: print(f[调试] i{i}, j{j}) j 1 i 1这样执行过程一目了然哪里出错一眼就能看出来。7. 九九乘法表的多种实现与优化7.1 九九乘法表的标准实现九九乘法表是嵌套循环的另一个经典案例它比小星星多了一层格式化输出的要求。i 1 while i 9: j 1 while j i: print(f{j}*{i}{i*j}, end\t) j 1 print() i 1输出1*11 1*22 2*24 1*33 2*36 3*39 ...这里有几个细节值得说第一end\t用制表符分隔比空格对齐效果好。因为乘法结果有1位数、2位数用空格对不齐用制表符能自动对齐。第二j i保证了每一行的列数递增形成三角形。第三f{j}*{i}{i*j}的格式j在前i在后符合乘法表的习惯。7.2 用for循环改写九九乘法表同样的逻辑用for循环写会更简洁for i in range(1, 10): for j in range(1, i 1): print(f{j}*{i}{i*j}, end\t) print()for循环省去了手动初始化和更新循环变量的步骤代码更短也更不容易出错。这也是为什么在实际开发中能用for的地方我尽量用for。7.3 对齐优化与格式美化九九乘法表默认用制表符对齐但如果终端宽度不同可能还是对不齐。更精确的做法是用格式化字符串指定宽度for i in range(1, 10): for j in range(1, i 1): print(f{j}*{i}{i*j:2d}, end ) print(){i*j:2d}表示结果占2个字符宽度右对齐。这样即使结果是1位数还是2位数都能对齐。如果你想要更美观的效果还可以加上边框或者用不同的分隔符。但核心逻辑不变都是嵌套循环加格式化输出。提示九九乘法表看似简单但它是检验你是否真正理解嵌套循环的好题目。如果你能不看参考、独立写出三种不同风格的九九乘法表while版、for版、带对齐优化的版本说明嵌套循环这一块你已经过关了。8. 循环实战中的常见问题与排查技巧8.1 循环不执行或执行次数不对这是新手最常见的问题。循环不执行通常是条件一开始就不满足。比如i 10 while i 5: # 条件一开始就是False循环体一次都不执行 print(i) i 1执行次数不对通常是边界条件写错了。比如想循环5次写成了i 5实际4次或者i 5实际5次但初始值如果是0就是6次。我的排查方法是在循环开始前打印循环变量的初始值在循环里打印每次的变量值在循环结束后打印总执行次数。三个打印一加问题基本就定位了。8.2 循环变量被意外修改有时候循环变量在循环体内部被其他逻辑意外修改了导致循环行为异常。比如i 1 while i 5: print(i) if i 3: i 10 # 意外修改循环提前结束 i 1这种问题比较隐蔽因为修改可能发生在函数调用、列表操作等间接路径里。排查方法是在循环里打印循环变量的值观察它的变化是否符合预期。8.3 嵌套循环里的break只跳一层这是一个非常容易误解的点。在嵌套循环里break只跳出它所在的那一层循环不会跳出所有层。i 1 while i 3: j 1 while j 3: if j 2: break # 只跳出内层循环 print(fi{i}, j{j}) j 1 i 1这段代码里内层循环每次都在j2时break外层循环继续执行。输出是三次i1, j1、i2, j1、i3, j1。如果你想一次性跳出所有层有几种方法方法一用标志变量found False i 1 while i 3 and not found: j 1 while j 3: if j 2: found True break j 1 i 1方法二把嵌套循环封装成函数用return直接返回def search(): i 1 while i 3: j 1 while j 3: if j 2: return # 直接结束整个函数 j 1 i 1方法二更优雅也是我更推荐的做法。8.4 常见问题速查表问题现象可能原因排查方法解决方案循环体一次都不执行初始条件不满足打印初始变量值检查初始值和条件表达式循环停不下来循环变量未更新在循环里打印变量确保循环变量在主干路径更新执行次数多一次或少一次边界条件写错手动模拟前几次和最后一次调整和continue后死循环continue跳过了变量更新检查continue位置把更新语句放在continue之前嵌套循环break跳不出去break只跳一层观察break后的执行路径用标志变量或封装函数累乘结果永远是0初始值设为0检查初始值累乘初始值设为19. 从循环到实战把基础变成能力9.1 循环在真实场景中的典型应用循环不只是练习题里的东西它在真实开发中无处不在。我举几个我自己遇到过的场景场景一批量处理数据。比如有一个用户列表需要对每个用户做某种操作这就是一个for循环。场景二读取文件内容。文件有多少行不知道用while循环逐行读取读到结尾停止。场景三重试机制。调用某个接口失败了需要重试几次用while循环加计数器控制重试次数。场景四生成报表。需要生成多行多列的数据嵌套循环是标配。场景五游戏或交互程序的主循环。用while True加break一直运行直到用户选择退出。这些场景的共同点是都需要重复做某件事而重复正是循环的强项。9.2 循环写得好不好的判断标准我总结了几条判断循环写得好不好的标准第一循环变量是否清晰。好的循环变量名一看就知道是干什么的初始化和更新位置一目了然。第二退出条件是否明确。不管是while的条件还是break的位置都应该让人一眼看出什么时候停。第三循环体是否单一职责。一个循环最好只做一件事如果循环体里塞了太多逻辑就该考虑拆分。第四是否有死循环风险。每个while循环都应该问一句它有没有可能永远不退出。第五嵌套层数是否合理。超过三层的嵌套循环可读性会急剧下降应该考虑用函数拆分。9.3 给初学者的练习建议如果你想真正掌握循环光看是不够的必须动手写。我建议按这个顺序练习第一步把本文里的每个例子都亲手敲一遍不看答案自己写出来。第二步改需求。比如把打印5行星星改成打印n行把九九乘法表改成加法表。第三步组合练习。比如打印一个菱形或者打印一个空心矩形。第四步做小项目。比如写一个猜数字游戏用while循环让用户一直猜直到猜对或者写一个简单的成绩统计程序用循环输入成绩统计平均分、最高分、最低分。第五步用for和while分别实现同一个功能体会两者的差异。我个人的体会是循环这个东西看十遍不如写一遍。你在写的过程中遇到的那些咦怎么不对的瞬间才是真正让你进步的地方。踩过的坑越多理解越深。最后再分享一个小技巧如果你在写循环时拿不准逻辑对不对就在纸上画一个表格把每一次循环的变量值都填进去手动模拟执行过程。这个方法看起来笨但极其有效尤其是对付嵌套循环和复杂的条件判断。我到现在遇到复杂的循环逻辑还是会先在纸上画一画确认无误再写代码。
阅读完成 · 觉得有帮助?