☰
Python第一次上机作业全解析:类型转换、条件分支与循环踩坑指南
2026/10/13 9:07:20 网站建设 项目流程

第一次拿到Python上机作业的时候,我盯着屏幕愣了半天——题目看着都认识,真到要写源码的时候,连print括号里的引号该用单还是双都要犹豫两秒。这份来自某高校的Python第一次上机作业,正好卡在"刚学完语法"和"会写程序"之间的那条线上。虽然题量不大,但每一道题都精准地踩中了新手最容易犯的错误:类型转换、边界条件、缩进习惯、代码可读性。这篇文章我会把完整题面和源码拆开揉碎,一边给代码,一边讲我当时是怎么想的、为什么这么写、以及上机时踩过的那些坑。如果你正在学Python,或者正准备带新生上机,这份拆解应该能省下不少功夫。

1. 作业全貌:第一次上机到底考什么

1.1 题面一览

我先把整理后的题面列出来。原题是纸质打印的,有些描述很口语化,我尽量还原当时的原始表述,只在格式上做了统一。

题号题目内容考察点
第一题输入姓名和年龄,输出"我是XX,今年XX岁,明年XX岁"变量定义、input输入、int类型转换、格式化输出
第二题输入一个0到100的百分制成绩,按照标准划分输出等级A/B/C/D/E,输入不合法要给出提示if-elif-else分支、逻辑运算符、输入校验
第三题输入一个正整数n,计算1到n的累加和,同时输出1到n之间所有能被3整除的数for循环、range区间、累加器、%取模

老实说,这三道题单独拎出来任何一道都不算难,但放在第一次上机作业里,梯度设计得很合理。第一题让大家熟悉"输入-处理-输出"的完整链路,第二题开始要求逻辑分支,第三题把你推进循环世界。最妙的是,第三题的"能被3整除"这个条件,让很多人第一次感受到取模运算符%的威力——代码里的一行,背后是数学里的整除概念。

1.2 出题意图:不是考你会不会,是考你熟不熟

我后来回看这份作业,发现它真正想训练的不是"会不会写",而是"熟不熟"。上机考试和笔试最大的区别在于:你必须让代码真正跑起来,而不仅仅是"觉得应该能跑"。

这里有个很容易被忽略的点:第二题的成绩分等级,乍一听是if-elif-else的练习,但实际上它考的是边界条件。59分和60分之间到底归哪一级?刚好100分算不算合法输入?-5分呢?很多同学写代码时逻辑通顺,但一跑测试就挂,就是因为这些边界值没兜住。

另外我也注意到,三道题全部依赖input()交互,这意味着你要有耐心一遍遍手动输测试数据。这里我建议你做一个习惯:把每次测试的输入值记在草稿纸上,比如0、59、60、85、100、-1、字符串"abc",跑完一遍打个勾。别嫌麻烦,这个习惯能帮你避开"只测了正常路径,快乐运行,然后一交上去就翻车"的尴尬。

2. 第一题拆解:输入输出与格式化,新手的第一道坎

2.1 题目复述与我的初版实现

"输入姓名和年龄,输出"我是XX,今年XX岁,明年XX岁"。"

这是全卷最简单的一题,但恰恰是最能拉开差距的一题。我当时的初版代码是这样的:

name = input("请输入姓名:") age = input("请输入年龄:") print("我是" + name + ",今年" + age + "岁")

跑起来没问题,但这版代码只完成了"今年",没算"明年"。于是我开始尝试在print里直接做加法:

print("我是" + name + ",今年" + age + "岁,明年" + age + 1 + "岁")

一运行,报错:

TypeError: can only concatenate str (not "int") to str

这就是新手遇到的第一类经典错误:字符串和整数不能直接拼接。input()返回的一定是字符串,age+1相当于把字符串和整数加起来,Python不允许这么干。

2.2 类型转换和格式化输出,哪个更顺手

解决问题有两个思路。

思路一,先把age转成整数,再算明年,最后输出时转回字符串:

name = input("请输入姓名:") age = input("请输入年龄:") age_int = int(age) next_age = age_int + 1 print("我是" + name + ",今年" + age + "岁,明年" + str(next_age) + "岁")

思路二,用f-string格式化输出,这是Python 3.6之后推荐的写法:

name = input("请输入姓名:") age = int(input("请输入年龄:")) print(f"我是{name},今年{age}岁,明年{age + 1}岁")

我强烈建议新手直接学f-string。原因不只是它代码更短,更重要的是它在表达"把变量的值嵌入字符串"这一需求时,逻辑最直观。你不需要来回记str()、int()的转换位置,只要在{}里写表达式就行。

2.3 一份带注释的参考源码

下面这份是完整版,覆盖了输入、类型转换、格式化输出三个知识点,也做了最基础的容错提示:

# 第一题:个人信息输出 # 知识点:input输入、int类型转换、f-string格式化输出 name = input("请输入姓名:") age_input = input("请输入年龄:") # input()返回的是字符串,必须先转成整数再参与运算 age = int(age_input) # 在f-string里可以直接写表达式,{age + 1}会被自动求值并格式化输出 print(f"我是{name},今年{age}岁,明年{age + 1}岁")

运行效果:

请输入姓名:小明 请输入年龄:18 我是小明,今年18岁,明年19岁

这里我想额外说一点:int(age_input)这行如果遇到用户输入"abc"会直接抛ValueError。第一次上机一般不要求做这种异常捕获,但你要知道有这个隐患。等到后面学到try-except,你就可以回头把这个作业升级成更健壮的版本——这是我很推荐的一种复习方式,拿旧题目练新知识,比做新题更省力。

3. 第二题:条件分支不等于一堆if

3.1 成绩等级划分的逻辑陷阱

题面要求:输入0到100的百分制成绩,按标准划分等级:90到100为A,80到89为B,70到79为C,60到69为D,60以下为E。

很多新手的第一个念头是写成一长串if:

score = int(input("请输入成绩:")) if score >= 90: print("A") if score >= 80: print("B") if score >= 70: print("C") if score >= 60: print("D") if score < 60: print("E")

这段代码有一个严重问题:如果输入95,它会同时打印A、B、C、D四行。因为四个if是依次独立判断的,95同时满足>=90、>=80、>=70、>=60。这就是新手对分支结构最大的误解——条件分支不是流水线,不是每道工序都要执行一遍;它是一个岔路口,你只能走其中一条路。

正确的做法是使用if-elif-else结构,让Python从上往下匹配第一个成立的条件,后面全部跳过:

score = int(input("请输入成绩:")) if score >= 90: grade = "A" elif score >= 80: grade = "B" elif score >= 70: grade = "C" elif score >= 60: grade = "D" else: grade = "E" print(f"成绩等级为:{grade}")

这样,95会走第一个分支,输出A之后整个判断结束。这个"从上往下第一个满足"的规则,是if-elif-else的精髓,也是我在上机时才真正理解的。

3.2 被忽略的边界值:-5、101和"abc"

第一次上机,老师给了一批测试数据,其中就有-5和101。许多同学写的代码在这两个输入上表现很"挫":-5被归到E,101被归到A。这就是边界条件没兜住。

加一层输入合法性判断,让程序对不合法的输入给出友好提示:

score = int(input("请输入成绩:")) if score < 0 or score > 100: print("输入不合法,成绩应在0到100之间") else: if score >= 90: grade = "A" elif score >= 80: grade = "B" elif score >= 70: grade = "C" elif score >= 60: grade = "D" else: grade = "E" print(f"成绩等级为:{grade}")

这里用到了嵌套if,外层先判断合法性,内层再判断等级,层次很清晰。or这个逻辑运算符也是第一次在这个作业里正式出现,它和and的区别可以这样记:or是"只要有一个成立就算成立",and是"必须全部成立才算成立"。

3.3 完整参考代码与测试用例

# 第二题:成绩等级判定 # 知识点:if-elif-else、逻辑运算符or、嵌套分支、输入校验 score = int(input("请输入成绩:")) # 先做输入合法性检查 if score < 0 or score > 100: print("输入不合法,成绩应在0到100之间") else: if score >= 90: grade = "A" elif score >= 80: grade = "B" elif score >= 70: grade = "C" elif score >= 60: grade = "D" else: grade = "E" print(f"成绩等级为:{grade}")

测试数据可以这样跑:

请输入成绩:95 成绩等级为:A 请输入成绩:60 成绩等级为:D 请输入成绩:101 输入不合法,成绩应在0到100之间 请输入成绩:-5 输入不合法,成绩应在0到100之间

留意60分这个数据。按照题目标准,60是D的起点,所以"if score >= 60"这个条件是包含60本身的。很多人容易把边界写成>60,导致刚好60分的人被分到E,考了60分的同学都要哭了。这就是我前面说的边界测试的意义:0、60、90、100这些临界值,必须逐一跑一遍。

4. 第三题:循环与取模,动手算一算

4.1 累加和的三种写法

题面要求:输入正整数n,输出1到n的累加和,同时输出1到n之间所有能被3整除的数。

累加和的实现,第一反应就是for循环加一个累加变量:

n = int(input("请输入一个正整数n:")) total = 0 for i in range(1, n + 1): total = total + i print(f"1到{n}的累加和为:{total}")

range(1, n + 1)这个写法值得展开说一下。range的区间是左闭右开,即range(a, b)包含a但不包含b。所以想要从1加到n,结束位置必须写成n + 1。我见过不少同学写range(1, n),结果发现总和少了一个n,怎么都找不出bug,最后打印i列表才发现问题。

还有一种写法是用while循环,很多教材喜欢在这里强调两种循环的对比:

n = int(input("请输入一个正整数n:")) total = 0 i = 1 while i <= n: total = total + i i = i + 1 print(f"1到{n}的累加和为:{total}")

while循环需要自己维护i的递增,如果忘记写i = i + 1这行,程序就会陷入死循环,上机时表现就是程序一直不结束,只能强制关闭窗口。相比之下,for循环把迭代变量管理封装在range里,新手使用起来更安全。第一次上机作业就让大家同时接触两种循环,目的就是让你亲身体会到这种区别,别等到考试了才知道。

4.2 能被3整除的数:%运算符的第一次亮相

输出"1到n之间所有能被3整除的数",核心就是判断i % 3 == 0。%是取余运算,i % 3的结果是i除以3的余数,余数为0就说明能被整除。

n = int(input("请输入一个正整数n:")) print(f"1到{n}之间能被3整除的数有:") for i in range(1, n + 1): if i % 3 == 0: print(i, end=" ")

注意print(i, end=" ")这里的end参数。默认情况下每个print都会换行,如果你想把多个结果输出在同一行,就用end=" "把默认的换行符替换成一个空格。这个是书上不太起眼但上机特别常用的知识点。

4.3 整合版本参考源码

把累加和、整除判断整合在一个循环里,可以少遍历一遍,效率更高,代码也更紧凑:

# 第三题:累加和与整除判断 # 知识点:for循环、range左闭右开、累加器、%取模、end参数 n = int(input("请输入一个正整数n:")) total = 0 print(f"1到{n}之间能被3整除的数有:", end="") for i in range(1, n + 1): total = total + i if i % 3 == 0: print(i, end=" ") print() print(f"1到{n}的累加和为:{total}")

运行效果:

请输入一个正整数n:10 1到10之间能被3整除的数有:3 6 9 1到10的累加和为:55

这里有一个小细节,print(i, end=" ")之后,光标停留在同一行末尾,所以紧接着的累加和输出需要先补一个print()换行,否则两行会黏在一起。我上机时第一次跑这段代码,看到数字后面直接跟着累加和,排查了好一会儿才意识到是换行的问题。

4.4 高斯的算法,写给学有余力的你

累加求和这道题,其实还存在一个数学捷径——等差数列求和公式:total = n * (n + 1) // 2。有同学交作业时会用这个公式,代码瞬间变成两行:

n = int(input("请输入一个正整数n:")) print(f"1到{n}的累加和为:{n * (n + 1) // 2}")

如果你是初学者,我建议第一遍还是老老实实写循环,因为循环结构本身是必须掌握的;但如果你已经能熟练使用for了,可以把公式版也写一遍,体会一下"同一个问题,不同算法,效率天差地别"的感觉。比如n等于1000万时,循环要执行一千万次,公式只要一次计算。这个对比会在你心里种下一颗"算法优化"的种子。

5. 上机踩坑实录:报错信息到底在说什么

5.1 三类报错,几乎每个人都会遇到

第一次上机课,教室里此起彼伏的报错声,我总结下来踩得最多的是这三类。

第一类,TypeError开头,比如"can only concatenate str (not 'int') to str"。这个在第一题里已经详细说过,本质是类型不匹配。养成一个习惯:input()取进来的东西,用之前先问自己"它现在是字符串还是整数"。

第二类,ValueError开头,典型的是"invalid literal for int() with base 10: 'abc'"。这通常发生在用户输入了非数字内容,而你的代码强行做了int()转换。第一次上机作业里第二题第三题都会触发这个问题。如果只是应付作业,不处理也过得去,但如果你希望代码更专业,就要学会用try-except兜底:

try: n = int(input("请输入一个正整数n:")) except ValueError: print("输入的不是整数,程序退出") exit()

第三类,IndentationError,报错信息里有"expected an indented block"或者"unexpected indent"。缩进是Python最特殊的语法规则,其他语言用花括号划分代码块,Python用缩进。很多同学在if里面写第二行代码时忘记缩进,或者缩进了一半空格一半Tab,程序直接罢工。我的建议是:编辑器里统一把Tab键设置为4个空格,不要混用。多数现代编辑器(比如常见的VS Code、PyCharm)都有"Tab转换为空格"的选项,打开之后就再也不会出现这类问题。

5.2 一套通用的调试思路

上面机课最重要的不是代码写得多快,而是遇到报错时能不能快速定位。我分享一个我自己用下来的三步排查法。

第一步,读报错信息最后一行。Python的报错是有层次的,最后一行通常是"错误类型: 具体描述",比如"TypeError: can only concatenate str (not 'int') to str"。这行直接告诉你发生了什么。

第二步,从下往上读Traceback。Traceback里会有一个文件名加行号,比如"File 'main.py', line 5",意思是出错位置在第5行。回到代码里看一下那一行的上下文,90%的情况你能立刻明白问题出在哪。

第三步,如果实在看不出来,就用print大法。在怀疑的位置前后加print,把中间变量的值打出来。比如循环累加后发现结果不对,就print一下i和total,看循环到底走了几轮、值到底是多少。这招虽然原始,但在第一次上机阶段比任何调试器都好用。

5.3 一个我印象深刻的错误:整数除法与浮点数

我们第三题里累加和有一段是total = total + i,如果i是整数,那么total一直是整数。但如果你不小心写了total = total + i / 2,情况就不一样了。Python 3里/运算的结果是浮点数,哪怕能整除也是浮点数,比如4 / 2的结果不是2而是2.0。这时候你后续的print输出就会带上".0",比如"55.0"。

这本身不算bug,但在成绩输出、格式化等场景下会带来显示问题。如果你想要整数除法的效果,应该用//运算符,比如n * (n + 1) // 2。这个细节第一次上机可能不会碰到,但迟早会遇到,提前知道总归是个好事。

6. 从"能跑"到"好读":代码质量的第一个分水岭

6.1 用函数把逻辑包起来

第一版能跑的代码,通常是平铺直叙的:input、判断、print一路写到底。这样交作业没问题,但代码一多就乱了。第二次上机老师要求"把每个功能写成函数",我回看这份作业,发现把这套思路用上其实很简单。

比如第三题,拆成两个函数就清晰很多:

def sum_to_n(n): """计算1到n的累加和""" total = 0 for i in range(1, n + 1): total = total + i return total def print_multiples_of_three(n): """打印1到n之间能被3整除的数""" for i in range(1, n + 1): if i % 3 == 0: print(i, end=" ") print() n = int(input("请输入一个正整数n:")) print(f"累加和:{sum_to_n(n)}") print("能被3整除的数:", end="") print_multiples_of_three(n)

函数的好处是:主程序变得很短,每个函数只干一件事,名字本身就说明了功能。而且以后遇到类似需求,直接复用函数就行,不需要再复制粘贴一长串代码。养成这种"模块化"的思维,从上机作业开始受益。

6.2 输入校验这层护身符,越早加越好

前面第二题里,我们已经尝试过校验成绩范围。如果你愿意多写几行,可以把输入校验封装成一个通用函数,让主流程专心处理业务逻辑,这也是专业代码里常用的一种写法:

def read_positive_int(prompt): while True: raw = input(prompt) try: value = int(raw) if value > 0: return value else: print("请输入正整数") except ValueError: print("输入的不是整数,请重试") n = read_positive_int("请输入一个正整数n:")

这段代码的核心是while True循环加return,不拿到合法的正整数就不退出。看似简单,但却是"程序和人交互"的标准做法。很多作业题只要求"输入合法数据时输出正确结果",但你多加这一层,哪怕输入乱七八糟的数据程序也不会崩,这就是专业性和普通作业的分水岭。

6.3 命名与注释:写给未来的自己

我第一次交作业时,变量名全用a、b、c,注释几乎不写,觉得写注释是浪费时间。后来过了一个月再翻这些代码,完全看不懂a和b是干什么的,只能重新推理。从那以后我坚持两个原则。

第一,变量名要有意义。name、age、score、total,一眼就看明白;而a、b、c要靠上下文猜。Python变量名本身不限制长短,别省那几个字母。

第二,注释写"为什么",不写"是什么"。像# 输入成绩这行注释就是废话,因为int(input("请输入成绩:"))这行代码已经说明了。真正值得写的是设计意图,比如# 先判断合法性再评级,避免-5被当成E级、101被当成A级。这种注释才能帮助未来的你——或者帮你批改作业的助教——快速理解你的思路。

代码可读性这个东西,第一次上机时看不出价值,但它是你以后读自己代码、和别人协作、应对大作业的底层能力。作业代码的运行结果只占30%,剩下70%评的是结构和习惯。这话我当时不以为然,现在回头看,真的一点不夸张。

最后想分享的一点经验

这份第一次上机作业,我前后一共写了四遍。第一遍磕磕绊绊地跑通,第二遍用f-string替换了所有的字符串拼接,第三遍把逻辑包进了函数,第四遍加了完整的输入校验。每一遍改动的代码都不大,但每一次重写都让我对某个知识点的理解深了一层。我现在带人入门时经常说:别怕重写自己的代码,这不是否定上一遍的劳动,而是在用新学到的东西给旧代码做一次升级——这种迭代式的练习,比刷十道新题管用得多。如果你也刚拿到自己的第一份Python上机作业,别急着抄答案,先把题面读懂,再试着独立写一遍,哪怕错了也没关系,报错信息里就有你进步的路线图。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询