☰
Python第3章练习题解析:数据类型、字符串与格式化输出避坑指南
2026/10/14 1:06:55 网站建设 项目流程

这几道题折腾了我两个晚上,说实话,刷《Python语言程序设计基础》第3章的练习题,最难受的不是不会写,而是“看答案觉得很简单,自己一写就报错”。嵩天老师的教材有个特点:例题讲得很透,但练习题偏偏不给你完整代码,只给你思路提示。这就逼着你自己去补中间的坑。这篇文章把我整理出来的第3章程序部分练习题的解题思路和参考答案整理成了一份笔记,同时把做题过程中容易踩的坑和背后的原理一并讲清楚,让正在啃这本书的读者不用再一个报错一个报错地试。

1. 第3章练习到底在练什么

1.1 这一章的定位:从“语法”跨到“思维”

学Python的人经常有一个误区,觉得语法看完就等于会编程了。但真正开始做嵩天老师第3章的练习题时,会发现事情没那么简单。第3章主要讲的是基本数据类型、字符串、数字运算和格式化输出,配套的练习题表面上看是在考语法,实际上是在逼你完成一次思维转换:把数学公式或者日常需求,拆解成Python能一步步执行的逻辑。

举个例子,书里要求你输入一个三位数,然后输出每个数字之和。这道题看起来只是考除法和取余,但它真正的用意是让你理解整数拆解的算法模型。很多人一开始会写a = int(input())然后直接a / 100,结果输出一堆小数,完全对不上。这个问题不是粗心,而是没有建立“整除//和取余%是拆解整数的一对工具”这个意识。

所以我的建议是:做第3章练习之前,先把两类东西封存在脑子里。第一是数据类型之间的转换规则,第二是格式化输出必须精确到客户需要的格式。这两类问题在练习题里占比最高,也最能拉开差距。

1.2 做题之前先搞明白的四件事

我把第3章习题里共通的基本功整理成了四个判断标准,每一道题做之前都先拿这四个标准过一遍,会少踩很多坑。

  • 输入是什么类型?input()拿到的一定是字符串,你要自己决定是否转成int或float。
  • 输出格式有什么要求?保留几位小数、要不要补零、数字之间用什么分隔符,这些必须在写代码之前想好。
  • 有没有边界条件?比如输入0、输入负数、输入空字符串,程序会不会崩。
  • 算法能不能在纸上推演一遍?哪怕是三位数求和这种简单题目,先用数学式子算一遍,再翻译成代码,准确率会大幅提升。

这四件事不一定每道题都涉及,但绝大部分练习题都能套进去。我把它们当成第3章的通用方法论,后续解题过程也基本按照这个顺序来推。

1.3 关于“参考答案”的说明

教材最后只给结果不过程序,网上能找到的版本又良莠不齐。我自己在做的时候,把同一道题尝试了两种甚至三种写法,最后整理出来的这套答案未必是唯一的,但至少保证:思路清晰、代码能跑、输出符合常规预期。更关键的是,我会顺便把错误版本和错误原因写出来,这比贴一个标准答案有用得多。

2. 数字计算与类型转换类习题解析

2.1 经典题:三位正整数各位数字之和

先看一道最典型的题目:“从键盘输入一个三位正整数,计算并输出各位数字之和。”这道题我在不同版本的书上见过很多次,它考察的就是整除与取余的组合使用。

快速看一眼正确解法:

num = int(input("请输入一个三位正整数: ")) hundreds = num // 100 tens = (num // 10) % 10 ones = num % 10 total = hundreds + tens + ones print(total)

这里最关键的是百位的计算。num // 100取的是整数商,比如543 // 100 = 5;十位是num // 10得到54,再对10取余得到4;个位直接对10取余得到3。每一步我把中间结果都打印出来验证过,这样对初学者来说最直观。

我之前见过有人这样写:h = int(num / 100)。虽然运行结果一样,但这并不是好习惯。因为/是浮点除,543 / 100 = 5.43,再int()强行截断成5,看起来没问题,但如果数字有浮点数参与运算,容易出现精度误差。而//是地板除,专门用于整数运算,在Python里两者的边界非常明确。我的建议是,在整数拆解的算法里统一用//和%,没必要混用/。

另外别忽略输入格式。如果你直接写num = int(input()),用户一旦输入带小数点的内容就会报错。好的程序应该提示用户“请输入三位正整数”,并且在讲解时强调:input()返回的是字符串,int()转换只能处理数字字符串,中间的转换过程本身就是这道题的一部分。

2.2 浮点数格式化输出:保留两位小数和百分号

第3章里另一类高频题是格式化输出。题目大概长这样:“输入一个浮点数,分别输出它保留两位小数的形式、保留两位小数的百分数形式,以及科学计数法形式。”这道题不只是考察round()函数,而是考察你是否掌握了字符串格式化的三种写法。

先给出一版稳定解法:

x = eval(input("请输入一个浮点数: ")) print("原值: {:.2f}".format(x)) print("百分数: {:.2%}".format(x)) print("科学计数法: {:.2e}".format(x))

这里我用了eval()而不是float(),是因为有些同学习惯输入3.14,有些会输1/3。eval()能把表达式算出来,但安全上是有隐患的,正常练习用没问题,正式开发不建议。如果输入的是3.14159,三种输出结果分别会是3.14、314.16%、3.14e+00。

容易犯错的地方是百分数的格式。很多人以为要自己先乘100再拼一个%符号,就像print(str(x * 100) + "%")。这样做虽然结果对,但代码笨重,而且位数控制非常麻烦。{:.2%}是直接把浮点数当作小数处理,自动乘100并追加百分号,是格式化里的内置特性,效率和可读性都更好。

还有一个细节:{:.2f}是“四舍六入五成双”还是常规四舍五入?Python的format采用银行家舍入法,跟数学课上的四舍五入略有差别。比如format(2.675, '.2f')会输出2.67而不是2.68,这是由浮点数的二进制存储决定的。考试中如果遇到精确舍入要求,建议用decimal模块,但这属于进阶内容,普通练习里只需要知道这个现象就够了。

2.3 注意运算顺序与类型陷阱

数字计算这一类题里,有个经典陷阱是运算符优先级。请看下面这行代码:

total = num // 100 + (num // 10) % 10 + num % 10

如果当初你没加括号,写作num // 10 % 10也没问题,因为//和%的优先级相同,从左往右算就是先整除再取余。但有些同学会把十位写成num // 10 % 10 + num // 100 % 10,看似差不多,其实结果会错位。为降低认知负担,我建议任何混合运算都显式加括号,哪怕你知道优先级,别人看代码也能一眼看懂。

另外类型转换上有一个常犯的错:把字符串和数字直接拼接。比如你要输出“计算结果为:15”,如果写成print("计算结果为:" + total),Python会直接抛TypeError。因为字符串不能和整数用+拼接,必须先把total转成字符串,或者直接用格式化语法。这个错误几乎每个初学者都会遇到,解决办法就是养成习惯:涉及输出的地方,要么写print("结果是:", total),要么用print(f"结果是{total}"),别手动拼字符串。

3. 字符串处理类习题解析

3.1 逆序输出与切片规则

字符串处理在第3章里占了很大的比重,其中出现频率最高的是逆序输出。“输入一个字符串,将其逆序输出”,看起来简单,却涉及Python切片中的步长概念。

正确写法:

s = input("请输入一个字符串: ") print(s[::-1])

这三个字符[::-1]看起来很玄,其实拆开就清晰了:第一个冒号前是起始位置默认0,第二个冒号后是结束位置默认末尾,第三个-1是步长,表示从右往左一个一个取。如果你写成s[:-1],那只是把最后一个字符去掉,跟逆序完全不是一回事。

还有一种常见题目是“输出字符串中的奇数位字符”或“每隔一个字符取一个”。这种题要用步长为2的切片实现:

s = input("请输入一个字符串: ") print(s[::2]) # 从0开始隔一个取一个 print(s[1::2]) # 从1开始,也就是偶数位置(从0计)

很多教材讲到切片会画图,但我个人更推荐用一个简单实验来记忆:先定义一个短字符串,比如"abcde",然后在交互式环境里试s[:]、s[::]、s[::-1]、s[1:4],把每次输出打印出来。用不了两分钟就能把索引规则彻底搞懂,比死记硬背强得多。

3.2 字符串字符统计与遍历

另一类必练题目是字符统计。“输入一行字符串,统计其中大写字母、小写字母、数字和其他字符的个数。”这类题的核心是学会用for循环遍历字符串里的每一个字符,并对字符类型做判断。

答案如下:

s = input("请输入一个字符串: ") upper = lower = digit = other = 0 for ch in s: if ch.isupper(): upper += 1 elif ch.islower(): lower += 1 elif ch.isdigit(): digit += 1 else: other += 1 print("大写字母:", upper, "小写字母:", lower, "数字:", digit, "其他:", other)

这题大家容易掉进去的坑有几个。第一个是忘记字符串是不可变对象,试图用ch = ch.upper()去修改原字符串。这里不需要修改,只需要把每个字符逐个检查。第二个是混淆isdigit()和isnumeric(),前者只判断0-9以及部分unicode数字字符,范围更窄;中文“一”用isdigit()判断是False,而isnumeric()是True。第三个是忘记处理空格,空格会进入else分支,归到“其他”中,这在统计里符合预期。

如果题目要求忽略大小写做统计,可以用s.lower()先把字符串统一转成小写,然后再遍历。记住:lower()返回的是新字符串,不会改变原变量,所以你要把返回值赋给一个新变量再使用。

3.3 format与f-string的实用细节

字符串格式化是第3章的暗线,几乎每道练习题的最后输出环节都会用到。我强烈建议在练习阶段就统一使用f-string或者format,而不是拿+去拼字符串。

f-string的基本用法:

name = "Python" score = 95.5 print(f"{name}的成绩是{score:.1f}分")

注意f-string在Python 3.6之后才支持,如果你的运行环境是Python 3.5及以下,就要用format()。教材可能还在教format(),但实际工作中f-string更常见,所以两种都要认识。这里有一个很实用的扩展:format指定宽度和填充符。比如输出“学号”对齐的表格时:

for i in range(1, 4): print(f"第{i:0>3}号")

输出会是“第001号”、“第002号”、“第003号”。0>3表示:总宽度3,用0在左边填充。这类写法在生成文件名、格式化时间时极其常用,练习题里虽然不直接考,但能帮你理解格式化机制的底层逻辑。

另外,format还支持千分位分隔符,比如f"{1000000:,}"输出1,000,000。第3章练习很少考到格式化输出复杂的嵌套,但如果你能掌握上面这些,做后面的数据处理章节会轻松非常多。

4. 综合应用题:从公式到程序的完整推演

4.1 用级数求π的近似值

第3章练习里有一道比较有代表性的综合题:“利用公式π/4 ≈ 1 - 1/3 + 1/5 - 1/7 + ... 计算π的近似值,直到最后一项的绝对值小于1e-6。”

这题综合了循环、条件判断、符号切换和浮点精度处理,是第3章从“语法”转向“算法”的桥梁。一个通用解法如下:

sign = 1 denominator = 1 total = 0.0 item = 1.0 while abs(item) >= 1e-6: total += item denominator += 2 sign = -sign item = sign / denominator pi = total * 4 print("pi =", pi)

这里需要重点解释的是循环的退出条件。每一次循环先把item加到total中,再更新denominator和sign,然后计算下一个item,再回到while判断条件。如果把item初始值设为1,那么第一轮加进去的就是1;第二轮是-1/3;这样通过不断交替正负号,就实现了公式的累加过程。

我踩过一个坑:在循环里把分母更新语句放错了位置。如果把denominator += 2放在item = sign / denominator之后,那么分母永远不会更新,程序会死循环或者结果不变。初学者遇到这种情况建议用一个计数器,比如设置一个max_iterations,限制最多循环十万次,防止无限循环把电脑卡住。虽然这题理论上会收敛,但程序里加一个保险丝能有效防止低级错误。

另外,当你把这个π值和math.pi对比时,会发现前几位一样,但后面有细微差距。这是正常的,因为级数收敛到精确π需要更多项,1e-6的精度只能保证前5位左右一致。教材这道题的目的,是让你理解“用迭代逼近一个数值”的思想,而不是让你得到精确π。

4.2 简单计算器:分支判断与类型转换

还有一种常见的综合题是“模拟简单计算器:输入两个数和一个运算符,输出结果”。题目大意:比如输入3 + 5,输出8.0;输入10 / 4,输出2.5。这不只是把三个值输入然后算一遍,还要考虑除数为0、非法运算符等边界。

参考代码:

a = float(input("请输入第一个数: ")) op = input("请输入运算符(+ - * /): ") b = float(input("请输入第二个数: ")) if op == "+": result = a + b elif op == "-": result = a - b elif op == "*": result = a * b elif op == "/": if b == 0: print("除数不能为0") else: result = a / b else: print("无效运算符") if op in ["+", "-", "*", "/"] and not (op == "/" and b == 0): if result.is_integer(): print("结果: {:.0f}".format(result)) else: print("结果:", result)

这里有一个练习时容易忽略的点:float(input())之后,如果用户输入3,Python会存成3.0,那么3.0 + 5.0 = 8.0。很多同学希望整数结果输出成8而不是8.0,就需要用is_integer()来判断。这个知识点在第3章正文里不一定重点讲,但练习题会用到,属于题后补充技能。我之前处理这个问题时直接用print("结果:", result),结果输出8.0,老师说严格不符合题目预期,于是我又用int(result)强转,但这样遇到3.5就会出错。is_integer()才是稳妥方案。

此外,注意elif结构。如果你用了四个独立的if,那么在输入非法运算符时,它可能把前面的分支也判断一遍,即使逻辑结果相同,效率更低。写分支时优先用elif串联,并能保证互斥。

4.3 温度换算类:换汤不换药的固定套路

教材前面的章节大概率出现过摄氏度和华氏度的换算。第3章练习里通常会升级为“输入一个带符号的温度值,例如100C或212F,自动转换并输出另一种单位”这样的题目。它结合了字符串切片、类型转换和分支判断,难度适中但综合性很强。

参考解法:

temp = input("请输入带单位的温度(例如100C或212F): ") if temp[-1] in ["C", "c"]: f = eval(temp[0:-1]) * 9 / 5 + 32 print("转换后的温度: {:.2f}F".format(f)) elif temp[-1] in ["F", "f"]: c = (eval(temp[0:-1]) - 32) * 5 / 9 print("转换后的温度: {:.2f}C".format(c)) else: print("输入格式错误")

这题的灵魂在temp[0:-1]。它从字符串中取出除了最后一个字符之外的所有数字部分,再交给eval或float转换成数值。如果你用int(temp[0:-1]),输入98.6F时就会抛异常,因为int()不能解析小数。更好的写法是float(temp[0:-1]),这样能同时兼容100和98.6。

还有一个隐藏细节:temp[-1]取的是最后一个字符,如果用户输入末尾带空格,比如"100C ",就会进入else分支,提示格式错误。这不是代码问题,而是输入规范问题。实际开发中可以用temp = temp.strip()先去空格,但在练习里,要求用户严格按格式输入也是合理的。

这类题的公共套路可以概括为三步:先确定标识位置,再切割数字部分,最后转换计算。温度换算、货币换算、成绩等级计算都是这个模板,换汤不换药。

5. 高频报错与排查实录

5.1 缩进和冒号:第3章出现最多的报错原因

写第3章练习时,新手的报错很大比例来自缩进和冒号。Python用缩进表示代码块,if、for、while、def的下一行必须缩进。很多同学在交互环境里复制代码时,缩进会变成空格和Tab混用,编辑器直接报IndentationError: unexpected indent。我的建议是把编辑器设置里的Tab自动替换成4个空格,或者干脆全部使用空格缩进。这跟你用什么系统无关,纯粹是编码习惯。

还有一种是“忘记冒号”。if、for、while、def语句行的末尾一定要有英文冒号。中文输入法全角冒号和英文半角冒号长得不一样,但Python只认英文冒号。如果你遇到SyntaxError: invalid syntax,优先检查上一行是不是把:写成了:。这是个非常低级的坑,但几乎每个人都踩过。

5.2 eval和float的取舍

很多标准答案喜欢用eval(input()),因为省事,数字或表达式都能处理。但eval()的本质是把字符串当成Python代码执行,如果你输入__import__('os').system('ls'),它真的会执行系统命令。做练习问题不大,但在实际项目里,这属于严重安全隐患。教材本身为了教学方便用了很多eval(),但我个人建议:处理数字输入时优先用float()或int(),这样程序更安全,也不会出现用户输入3 + 5时直接计算出8的情况(有时候这反而不符合出题意图)。

如果确实需要用eval,也要限定输入内容。你可以先判断字符串是否只包含数字、小数点和运算符,再交给eval()执行,这样能降低一部分风险。不过对第3章练习来说,直接记住“普通输入用float,要用表达式才用eval”这个原则就够了。

5.3 浮点数精度导致的结果偏差

很多同学在计算温度换算时,明明公式对,结果却出现100.00000000000001这样的数字。这不是你算错了,而是浮点数二进制存储的固有问题。第3章练习通常不会让你处理这种精度细节,但你需要形成共识:凡是要输出给人看的结果,一律用格式化输出控制小数位数。不要依赖print的默认精度,它只会忠实地展示内存里的值。

如果在调试时发现了精度问题,可以用round(result, 2)临时查看,但注意round()返回的是浮点数,如果你接着做运算,仍然可能出现新误差。真正的解决办法是用Decimal或者格式化成字符串后再输出。这个知识点在后面网络爬虫和数据分析的章节会反复出现。

5.4 字符串索引越界与空输入

最后记录一个高频异常:IndexError: string index out of range。这个错误经常出现在需要取字符串首尾字符的题目中。例如上面温度转换题,如果用户直接按回车不输入内容,temp[-1]就会越界。解决办法是在取索引之前先判断字符串长度:

if len(temp) > 0: ...

还有一个相关的坑:把用户输入的字符串直接用于切片,比如temp[0:-1]要求字符串至少长度为2。如果用户只输入"C",切片得到空字符串,float("")会报错。所以综合题里,建议先判断长度,再判断单位字符,最后才做数值转换,顺序不能反。我见过很多同学的逻辑是先转换再判断单位,结果单字符输入直接让程序崩溃。练习的时候养成先校验再计算的习惯,对后面做工程项目非常有帮助。

6. 解题以外的几点体会

整理完这些习题,我最深的感受是:第3章的练习题并不是为了为难你,而是逼着你在“读代码”和“写代码”之间建立一座桥。很多人卡在某一题上,并不是因为语法不会,而是因为没掌握拆解问题的顺序。比如拿到“温度转换”这一题,你先别急着写代码,先在纸上写下输入是什么、输出是什么、中间有几步,然后再翻译成Python。这个习惯一旦养成,之后学函数、学类、学文件操作都会顺利很多。

还有一个我自己的体会是“先跑通,再优化”。做练习题时,第一版代码通常又长又笨,比如用一堆if处理输入格式,这不丢人。先让程序在任何输入下都不崩溃,再去考虑用更巧妙的列表推导、字典映射来简化代码。用第3章的知识能解决的题目,就先用第3章的知识解决,硬套后面的高级语法反而会让思路混乱。

最后再分享一个小技巧:书里每个练习题的输出格式往往藏有玄机。有的要求空格分隔,有的要求逗号分隔,有的要求保留固定小数位。提交之前一定要把输出示例和你的输出逐字符比对一遍。我遇到过不少次“代码正确但输出格式多了一个空格”导致的报错,这种题目不是考算法,是考细心。能把第3章的题做到“一次过”,说明你真的开始像一个程序员那样思考了。

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

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

立即咨询