Python实验二流程控制通关指南:循环、缩进与调试避坑

发布时间:2026/10/11 7:24:04
Python实验二流程控制通关指南:循环、缩进与调试避坑
如果你正在做Python实验二的第11到20题估计已经跟if、else、for、while打得火热了。前面的题如果说是认识语法那从这10道题开始就是逼着你去想“这个逻辑到底怎么用代码表达”。我当初做这组题的时候最明显的感觉是书上的例题一眼能看懂但轮到自己去写总是差一口气——不是漏了边界条件就是循环里变量位置放错。这篇就把我做这组题时啃过的骨头、踩过的坑逐条展开给你一个可以直接参考的解题思路和避坑清单。我不是要替你写作业而是想告诉你流程控制这关过了Python后面很多东西都会顺很多。文章里我会把核心语法点重新讲一遍再挑几道典型的第11到20题做拆解最后把调试时容易踩的坑整理成速查表。无论你现在是被循环绕晕还是被缩进搞得头疼看到最后应该都能找到解决办法。1. 实验二到底在练什么流程控制的三块硬骨头1.1 三种结构顺序、选择、循环程序流程控制说白了就是让代码按照你设定的路线去走。Python里面最基本的路线有三种顺序、选择、循环。顺序结构最好理解就是从上往下一行一行执行。选择结构靠if系列语句让程序在不同条件下走不同分支。循环结构则是让一段代码重复执行可以用for或while来表达。第11到20题看起来题型丰富其实内核就是在考这三样东西的组合。比如有一类题是“累加求和”它考的是循环里的累加器写法有一类题是“判断一个数是不是素数”考的是if和for的配合还有一类题是“输出一个三角形”考的是嵌套循环。你会发现脱离这三种结构这些题根本没法做。我见过不少同学做后面的题时习惯把一小段代码复制来复制去或者用几十个if硬堆结果。这样做也许能过几个测试点但遇到边界条件比如n1、输入为0、循环一次都不执行代码立刻就露出破绽。流程控制题的真正考点不是你会不会写if而是你能不能把条件想全、把循环边界算清楚。1.2 为什么11到20比前面10题更值得抠通常实验二会安排20道题左右前10题偏语法认知后10题偏逻辑综合。11到20的难度梯度会很明显一开始可能只是单层循环加一个条件判断到后面就会变成双层循环、多条件组合、循环里嵌套分支甚至要用到break和continue。这套题最适合拿来练“读题—拆解—写码—调试”的完整流程。因为题目已经给了明确输入输出测试点往往藏在边界值里。你写完代码后至少要自己测几组数据最小的输入、最大的输入、等于阈值的输入、不满足条件的输入。很多同学做实验只复制别人代码结果考试时相似的题换个条件就不会了根子就在于平时没有主动去抠这些细节。我建议你做这10道题时每道题都经历三步第一步用自然语言把解题思路讲给自己听第二步画一个简单的流程图哪怕是手画几个框和箭头都行第三步再动手写Python代码。这样的话代码就不再是灵光一现的产物而是有逻辑支撑的作品。2. 核心语法细节别在基础地方翻车2.1 缩进与代码块Python的“颜文字”Python用缩进来表示代码块的归属这一点不夸张地说是新手翻车最多的地方。其他语言有{}Python没有所以同一个for循环体里的代码必须严格对齐。最常见的问题是Tab键和空格混用。有的编辑器里Tab默认是4个空格有的默认是8个一旦混用看着缩进一致实际Python会直接报IndentationError。我的建议很简单全队统一用4个空格在编辑器里把Tab自动转换成空格。另一个问题是缩进层级搞错。比如for i in range(3): print(i) print(done)这段代码中print(done)不受循环控制所以循环结束后会执行一次。但如果把print(done)多缩进一层for i in range(3): print(i) print(done)那done会在每次循环里都打印一边。实验题里经常要求“循环结束后输出统计结果”很多人就是在这里缩进多了一格导致结果完全不对。检查缩进时别用眼睛大略扫可以用编辑器的缩进引导线或者把代码折叠起来看层级。2.2 if/elif/else 的条件判断易错点条件判断里有两个高频坑一个是和混淆另一个是条件优先级。赋值是一个等号比较是否相等是两个等号。这个错误在Python里有时候不会直接报错因为表达式if x 5会报语法错误但如果你写成if 5 x:虽然能运行但逻辑上可能不是你想要的。把常量写在左边是一种防御性写法但Python里通常不需要我更建议你用有意义的变量名别用a、b、c这种。多条件组合时and、or、not的优先级要清楚not最高其次是and最后是or。如果你写if a 1 or b 1 and c 1:Python会先算b 1 and c 1再和a 1取或这可能和你的直觉不一样。遇到这种表达式强烈建议加括号既安全又利于别人阅读。还有一个细节判断一个数是否在某个范围内可以写成链式比较比如if 10 x 20。这在很多实验题里很实用但有的同学习惯写成if 10 x and x 20也没错但链式更直观。2.3 for和while的选择逻辑for循环适合循环次数确定的场景while循环适合循环次数不确定、靠条件退出的场景。很多题用for写更简洁比如“从1加到n”直接写n int(input()) total 0 for i in range(1, n 1): total i print(total)这里的关键是range(1, n 1)。range的边界是左闭右开也就是包括起始值、不包括结束值。如果你写成range(1, n)结果就会少一个n。这种边界问题在实验题的测试点里几乎必考尤其是你刚好输入的是偶数、边界值、或者等于某个关键数的时候。while循环则要特别注意终止条件。比如“不断输入整数直到输入0为止”你可以写total 0 while True: num int(input()) if num 0: break total num print(total)用while True加break是合法的但要注意如果你忘了写break或者break的条件永远不成立就会死循环。死循环在实验评测系统里通常表现为“运行超时”。2.4 break、continue、else在循环中的正确用法break是终止整个循环continue是跳过本轮进到下一次。这两个词看起来简单实操中很容易位置搞错。比如你要把1到10里的偶数打印出来用continuefor i in range(1, 11): if i % 2 ! 0: continue print(i)这个逻辑是奇数跳过偶数打印。如果你把print(i)放在了continue前面那就白跳了。还有一个很多人不知道的语法for...else和while...else。else块只有在循环正常结束没有遇到break时才执行。这个特性特别适合判断素数、查找元素这类场景。比如判断一个数是不是素数n int(input()) for i in range(2, int(n ** 0.5) 1): if n % i 0: print(不是素数) break else: print(是素数)如果循环里找到了因数就会breakelse不执行如果循环从2到根号n都跑完了也没找到因数else就会执行。这种写法比设置一个标志位再判断要清晰得多。不过要注意else的缩进是跟for对齐不是跟if对齐这也是很多人容易出错的地方。3. 实操过程第11到20题我挑这5道典型题拆给你看3.1 题11累加求和含步长与边界题目大概长这样输入一个正整数n计算1到n之间所有能被3整除的数的和。不同学校的表述可能会有差异但核心都是“循环累加”。思路很简单先建一个累加器total0然后用for遍历1到n每遇到一个能被3整除的数就加到total里。关键点是边界n本身可能也能被3整除所以循环范围要包含n也就是range(1, n1)。n int(input()) total 0 for i in range(1, n 1): if i % 3 0: total i print(total)我见过有人把range(1, n)写成range(1, n 1)时心里犯嘀咕担心多加一个数。实际上range是“取头不取尾”所以想包含n就得把结束值写成n 1。这个边界要想清楚最好在代码注释里写明白。如果题目改成“计算1到n之间所有奇数的和”那还可以用步长优化n int(input()) total 0 for i in range(1, n 1, 2): total i print(total)这样循环只遍历奇数效率更高逻辑也更简洁。不过要注意如果n是偶数range(1, n1, 2)遍历的是1、3、5...一直到n-1或n不会误包含偶数所以没问题。这里的经验是能用步长解决的条件就别在循环体里用if判断代码更干净。3.2 题14判断素数素数题的通用场景是输入一个正整数n判断它是否是素数。这个题在流程控制实验里几乎必考因为它同时考了循环、条件判断和break/else的配合。先说特殊值1不是素数2是素数。很多人忘了处理n1结果程序会进入循环然后range(2, 2)是空范围循环不执行else却执行了于是把1判断成素数。这就很尴尬。所以必须单独处理n int(input()) if n 2: print(不是素数) else: for i in range(2, int(n ** 0.5) 1): if n % i 0: print(不是素数) break else: print(是素数)为什么要遍历到int(n ** 0.5) 1因为如果n有大于根号n的因数那必然也有一个小于根号n的因数。比如n15根号约3.87因数3就能判断出来。所以遍历到根号n就够了这是数学上的常识在程序里能省很多无用功。还有一个优化可以考虑偶数除了2都不是素数。所以如果n大于2且是偶数可以直接判非素数。但我觉得在做实验题时先把基础版本写对更重要。这道题最容易被测试点卡住的地方就是n1、n2、n3和n4。你可以自己拿这几个数分别跑一遍确认输出符合预期再提交。3.3 题16水仙花数水仙花数指一个三位数它的每个位上的数字的立方和等于它本身。比如153 1³ 5³ 3³。常见题目是输出所有三位水仙花数或者判断某个三位数是不是水仙花数。拆位是重点。给你一个三位数n个位是n % 10十位是n // 10 % 10百位是n // 100。有的人会搞错整除和取余的优先级其实//和%的优先级同乘除所以n // 10 % 10会先整除后取余刚好能得到十位。如果要输出100到999范围内的所有水仙花数for num in range(100, 1000): bai num // 100 shi num // 10 % 10 ge num % 10 if bai ** 3 shi ** 3 ge ** 3 num: print(num)这里不需要三层循环直接单循环加拆位就行。有些同学看到“每个位数”就觉得要嵌套循环其实是把问题想复杂了。实验题里偶尔会有“嵌套循环”的考察点但水仙花数用单循环拆位更简单。另一个容易出错的点是**运算符的优先级。bai ** 3 shi ** 3 ge ** 3会先算三次方再相加这没问题。但如果你写成bai * bai * bai也要小心别漏掉一个bai。如果你要判断输入的三位数是否为水仙花数代码结构也类似只是把num变成输入值。判断完别忘了输入可能是三位数范围外的值比如输入1000这时候算出来的bai1, shi0, ge0虽然也能算但严格意义它不是一个三位数题目一般会保证输入合法但你最好在代码里加个范围判断以防万一。3.4 题18打印直角三角形星号打印图形是流程控制实验里最考验嵌套循环的题。常见的描述是输入一个正整数n输出一个n层的直角三角形第一层1个星号第二层2个星号依此类推。代码很经典n int(input()) for i in range(1, n 1): print(* * i)这个解法用字符串乘法非常简洁。但有些实验题指定“不能使用字符串乘法”或者想考你嵌套循环的写法那你就得用两个forn int(input()) for i in range(1, n 1): for j in range(i): print(*, end) print()外层循环控制行数内层循环控制每一行星号的个数。print(*, end)表示不换行输出完一行后再用一个空的print()换行。这个print()千万别漏漏了的话所有星号会挤在一行输出完全不对。如果你要做倒三角形或者靠右对齐的三角形思路相同只是要在内层循环之前先打印一些空格for i in range(1, n 1): for j in range(n - i): print( , end) for j in range(i): print(*, end) print()这段代码中空格数量是n-i星号数量是i。打印空格那层循环要注意是n - i不是i - 1。我当时就在这里栽过测试点输出全部对不齐。建议你在本地编辑器里把输出分散显示出来看看每一行的空格数是否符合预期。九九乘法表也是这个套路。很多学校会把九九乘法表放在流程控制实验里如果你能独立写出乘法表那嵌套循环基本就过关了。3.5 题20猜数字小游戏实验二最后的题经常是一个综合应用比如“猜数字”。常见规则程序先随机生成一个1到100的整数然后你不断输入数字根据反馈提示“大了”或“小了”直到猜中为止。用到的知识点包括import random、while循环、if判断、break甚至还有input类型转换。示例代码import random target random.randint(1, 100) while True: guess int(input(请输入你猜的数字)) if guess target: print(小了) elif guess target: print(大了) else: print(猜对了) break这个代码看起来简单但里面有三个容易踩的坑第一个坑是random.randint(1, 100)是包含1和100的和range不同。很多人刚从range过来下意识以为randint(1, 100)不包含100其实它包含。第二个坑是int(input(...))的转换。如果你输入的是小数或者字母int()会直接抛ValueError程序崩溃。实验评测系统一般不会给你奇怪的输入但如果你在自己玩这个游戏就可以加上try...except做容错。第三个坑是死循环。理论上break在猜对时会退出但如果你把break缩进错了或者写成continue那永远退出不了。在调试的时候如果程序一直让你输入就先检查break在不在正确的位置。如果想给这个游戏增加一点挑战可以加一个计数器import random target random.randint(1, 100) count 0 while True: guess int(input(请输入你猜的数字)) count 1 if guess target: print(小了) elif guess target: print(大了) else: print(f猜对了一共猜了{count}次) break这种题的评分标准一般只关心你能不能跑通但如果你在实验报告里写清楚“用计数器统计猜测次数”老师印象分会好很多。4. 实验中的常见问题与排查实录4.1 死循环与条件写反死循环是流程控制实验里最让人崩溃的问题之一。典型场景i 1 while i 10: print(i)这段代码里i永远不会变所以会一直打印1。解决办法很简单在循环体里加上i 1。但有时候你加了还是死循环那就需要检查条件是不是写反了比如while i 1条件永远为真。排查死循环最快的方法是在循环体里加入一个print(i)观察变量变化。如果打印出来的数值不更新说明你没修改变量如果数值在更新但永远到不了终止条件说明循环条件或步长有问题。还有一招是临时把循环次数限制一下比如i 1 while i 10: print(i) i 1 if i 100000: break这不算正规解法但调试时能防止程序卡死比直接让系统“运行超时”强。4.2 变量作用域与累加器重置累加求和的题里最常见的错误是累加器放在了循环里面。n int(input()) for i in range(1, n 1): total 0 total i print(total)这样写每次循环都会先把total重置为0最后输出的只是n本身而不是总和。累加器必须在循环开始之前初始化。这个概念特别基础但在高度紧张写作业时超级容易犯尤其是从别的语言刚转过来的时候。如果是嵌套循环内层循环里的计数器也需要在进入内层循环前重新初始化否则会累积上一次循环的结果。比如打印三角形时for i in range(1, n 1): count 0 for j in range(i): count 1 print(count)这里count0必须放在外层循环内、内层循环外。如果你把它放在程序最上方第二行开始count就会继续累加结果变成1、3、6、10……完全不是你想要的效果。我在调试这种问题时的经验是先看变量在哪几行被赋值再确认赋值语句的位置缩进是不是符合层级关系。4.3 格式化输出对不齐实验题经常要求“输出结果占几位、右对齐、保留几位小数”。如果你只用print拼接很容易出现输出对不齐的情况。推荐用f-string或format。比如要求输出1到10的平方每个数占4位右对齐for i in range(1, 11): print(f{i:4} {i ** 2:4}):4就是右对齐、最小宽度4的意思。如果输出小数可以用{x:.2f}保留两位小数。打印图形时空格和星号的数量错一点就满盘皆输。我的建议是先在草稿纸上画一个小一点的例子比如n3把每一行的空格数、星号数都列出来再翻译成range代码。这样比直接凭空写嵌套循环靠谱多了。另外要注意有的评测系统对行末空格非常敏感。你如果多打了一个空格它可能会判“格式错误”。用end时尤其要注意每行输出完之后要么用print()换行要么用end\n不要把不该有的东西输出出去。4.4 输入类型错误导致比较失败input()返回的是字符串如果直接拿它和数字比较哪怕值是同一个数也会因为类型不同而报错或者逻辑错误。比如num input() if num 10: print(big)Python 3里字符串和整数比较会直接抛TypeError因为类型不同不能比较。所以必须在输入后立刻做类型转换num int(input())如果你要输入两个数别写成a int(input()) b int(input())这样一行一个输入题目一般会给“两个整数之间用空格分隔”那你要用a, b map(int, input().split())split()默认按空白字符分割空格、制表符都能分开。map(int, ...)把分割后的每个字符串转成整数再解包给a和b。这个写法在实验题里相当常用一定要会。4.5 常见问题速查表现象原因解决办法程序运行超时死循环检查循环变量是否更新、条件是否正确、是否忘了breakIndentationErrorTab与空格混用、缩进层级不齐统一用4个空格开启编辑器空白字符显示累加结果不对累加器放在了循环内把初始值放在循环之前多了一个循环次数range结束值写错记住range左闭右开包含结束值则写stop1输出全在一行忘记换行每行输出后加print()或\n三角形不对齐空格数量算错手动推演n3的情况再改代码输入多个整数报错用错了输入解析方式用map(int, input().split())循环里的else不执行缩进错位else必须和for/while对齐不是和if对齐随机数范围不对randint与range混淆randint包含两端range不包含结束这张表是我做这组题时自己整理出来的。遇到问题别急着翻答案先对照表格定位再打印几个中间变量看看基本都能解决。最后说点实在的。实验二的11到20题真正难的不是语法而是“把脑子里的逻辑捋顺”。我做完这组题最大的体会是一定要自己画流程图画完再写代码代码写完再故意去找边界值测试而不是样例通过就交。你每多想一个边界条件后面考试就少一分慌。做错的题不要改完就扔把错因记下来过两天再重新做一遍。流程控制这一关一旦打通后续的函数、文件、面向对象都会学得轻松很多。