查看全课大纲(第 20 / 51 节)
- 1.为什么人人都该学点编程?
- 2.计算机与程序设计:你的电脑到底在“想”什么?
- 3.Python 这门语言,到底有什么魔力?
- 4.Python 开发环境配置:如何拥有你的第一个“编程工具箱”?
- 5.如何安装一个更强大的代码编辑器?
- 6.汇率兑换1.0:你的第一个“钱生钱”小程序
- 7.你的第一行代码,藏着哪些秘密?
- 8.汇率兑换2.0(上):让程序看懂“CNY”和“USD”
- 9.汇率兑换程序,如何让它“聪明”地判断币种?
- 10.汇率兑换程序能一直运行,直到我喊停吗?
- 11.汇率兑换4.0:如何把“算钱”功能打包成积木?
- 12.汇率兑换5.0:给你的程序穿上“结构化”的西装
- 13.怎么用 Python 画一个会动的五角星?
- 14.如何让程序自动画出不同大小的五角星?
- 15.函数自己调用自己,会发生什么?
- 16.用递归画出神奇的分形树
- 17.Python 怎么计算你一天躺着不动能消耗多少热量?
- 18.如何让程序“活”起来,持续为你服务?
- 19.如何让 BMR 计算器更“聪明”?
- 20.当程序遇到“不按套路出牌”的用户怎么办?
- 21.怎么用 Python 模拟一个“滚雪球”式的存钱计划?
- 22.如何用列表记录每一周的存款?
- 23.如何让程序自己数数?—— 用 for 循环解放你的双手
- 24.52周存钱挑战4.0:你的存款计算器能有多灵活?
- 25.52周存钱挑战:怎么根据日期自动查存款?
- 26.Python 怎么判断一年中的第几天?
- 27.列表 vs 元组:哪个更适合存储月份天数?
- 28.用集合给月份分个队,换个思路算天数
- 29.把月份和天数“锁”在一起:用字典给数据配个对
- 30.Python 怎么判断密码强弱?
- 31.Python 怎么给密码设置“防沉迷”系统?
- 32.Python 怎么把密码保存到文件里?
- 33.Python 怎么读取文件里的密码?
- 34.Python 怎么把密码检查工具“打包”起来?
- 35.Python 怎么把文件操作也“打包”起来?
- 36.计算机怎么“扔骰子”?——用Python模拟随机事件
- 37.如何用 Python 模拟掷两个骰子?
- 38.怎么用 Python 把骰子轨迹画出来?
- 39.骰子点数分布长啥样?用直方图一眼看穿!
- 40.用科学计算库让骰子程序“起飞”
- 41.空气质量指数怎么算?手把手教你写一个AQI计算器
- 42.空气质量指数计算:从零开始,让程序看懂空气
- 43.如何读取空气质量数据文件并找出空气质量最好的五个监测点?
- 44.JSON 数据怎么变成 Excel 表格?—— 让数据换个“马甲”
- 45.Python 怎么让程序自己判断文件类型?
- 46.如何让程序自己上网查空气质量?
- 47.用美味的汤来解析网页:Beautiful Soup 入门
- 48.如何让爬虫自动抓取全国所有城市的空气质量?
- 49.爬到的数据怎么存下来?—— 把全国空气质量数据保存为CSV文件
- 50.用 pandas 玩转空气质量数据:找出全国空气最好和最差的城市
- 51.空气质量数据怎么“洗”干净,还能画成图?
当程序遇到“不按套路出牌”的用户怎么办?
约 15 分钟
小象实战讲义 · Python 入门:8 个小项目边玩边学
上一节,我们让BMR计算器变得“善解人意”,能在一行里接收所有信息。但程序还是有点“玻璃心”——只要用户输入的不是数字,比如把“70”输成了“七十”,它就会直接崩溃,留下一堆看不懂的错误代码。
这一节,我们就来给程序穿上“防弹衣”,让它遇到“不按套路出牌”的用户时,也能优雅地处理,给出友好的提示,而不是直接“摆烂”崩溃。你的程序将变得更健壮、更专业。
💡 核心导读
- 问题引入:模拟一个“捣蛋”用户,看看程序崩溃时有多吓人。
- 新知识点:认识Python的“保镖”——
try...except异常处理机制。 - 实战应用:为BMR计算器添加异常处理,让它能从容应对各种错误输入。
- 知识巩固:回顾本章所学,并预告下一个处理“一系列数据”的精彩项目。
一、当程序遇到“捣蛋鬼”
还记得我们上节课末尾留下的悬念吗?如果用户不输入数字,而是输入了“七十”、“一米八”这样的文字,程序会怎样?让我们来当一回“捣蛋鬼”用户,亲自试试看。
假设我们运行程序后,故意乱输入:
- 是否退出?
n(不退出) - 请输入信息:
男 七十 175 25(注意,体重这里写的是“七十”)
猜猜会发生什么?
程序会瞬间“爆炸”,在屏幕上打印出一大段红色的错误信息,最后以 ValueError: could not convert string to float: '七十' 结尾,然后彻底停止运行。
对于一个完全不懂代码的用户来说,这简直就像电脑突然蓝屏一样让人恐慌。他们会觉得:“这什么破程序,一点也不好用!” 这可不是我们想看到的。
我们的目标:就算用户输错了,程序也应该温柔地提醒,比如“请输入正确的数字哦~”,然后让用户有机会重新输入,而不是直接“死”给你看。
二、请出程序的“保镖”:try...except
Python早就为我们想到了这种情况,并提供了一个超级好用的“保镖”机制——异常处理,对应的代码结构是 try...except。
你可以这样理解:
try(尝试):把你觉得可能会出问题的代码放进这个“保护罩”里。except(除了/捕获):如果“保护罩”里的代码真的出错了(发生了“异常”),就执行except后面的代码来“兜底”。
它的基本长相是这样的:
try:
# 把可能出问题的代码放在这里
# 例如:把用户输入的字符串转换成数字
risky_code_here
except 错误类型1:
# 如果发生了“错误类型1”,就执行这里的代码
handle_error1
except 错误类型2:
# 如果发生了“错误类型2”,就执行这里的代码
handle_error2
except Exception:
# 这是一个“万能捕获器”,可以捕获绝大多数运行时错误
handle_all_other_errors小提示:上面最后一种也可以简写成裸的
except:,但它会“贪婪地”连KeyboardInterrupt(Ctrl+C 中断)、SystemExit这类系统级信号也一并捕获,导致你连想强制退出程序都退不掉。所以正式代码里推荐写except Exception:——它覆盖普通错误,却放行了系统退出信号。
它是怎么工作的?
- Python先尝试执行
try里面的代码。 - 如果一切顺利,没有错误,它就跳过所有
except,继续执行后面的程序。 - 如果
try里面的代码出错了,Python就会立刻停止try块内的执行,然后从上到下检查是哪个except能“抓住”这个错误。 - 找到匹配的
except后,就执行它里面的“兜底”代码。执行完后,程序会继续正常往下走(而不是崩溃)。
这就好比你去尝试一个高难度动作(try),旁边站着教练(except)。你做成功了,万事大吉。你做失败了,教练立刻扶住你,防止你摔伤,并给你指导,然后你可以继续练习。
三、给BMR计算器穿上“防弹衣”
现在,我们就用这个“保镖”来升级我们的BMR计算器。核心思路是:把用户输入、分割字符串、转换数字类型、计算BMR这一整套流程,都放到 try 的保护罩里。
第1步:识别“危险地带”
在我们当前的代码中,哪里最容易“爆炸”? 答案就是把字符串转换成数字的这三行:
weight = float(str_list[1]) # 把体重字符串转成浮点数
height = float(str_list[2]) # 把身高字符串转成浮点数
age = int(str_list[3]) # 把年龄字符串转成整数(上面这三行是从完整程序里摘出来的”危险地带”,str_list 由上一节的 input_str.split(' ') 得到,所以单独运行会找不到它——下面第 2 步我们会把它们完整地放回程序里。) 如果 str_list[1] 是 "七十",float("七十") 肯定会失败。
第2步:构建“保护罩”
我们用 try 把从输入到计算的整个逻辑包起来。同时,我们要捕获最常见的错误——ValueError(值错误,通常就是类型转换失败)。
下面是升级到4.0版本的完整代码。注意:为了你能直接复制运行,我们把整个程序写在一个代码块里,并且用固定值代替了 input()。
"""
作者:小象教研组
功能:BMR计算器
版本:4.0
描述:处理用户的异常输入,让程序更健壮
"""
def main():
"""主函数"""
# 原程序这里用 input('是否退出程序(y/n)?'),为了方便运行,我们固定为 'n'(不退出)
y_or_n = 'n'
while y_or_n != 'y':
print('请输入以下信息,用空格分割')
# 原程序用 input('性别 体重(kg) 身高(cm) 年龄:')
# 我们用一个会引发错误的输入来演示:'男 七十 175 25'
input_str = '男 七十 175 25'
print(f'用户输入的是:{input_str}')
str_list = input_str.split(' ')
try:
# 尝试执行可能出错的代码
gender = str_list[0]
weight = float(str_list[1]) # 这里可能会出错!
height = float(str_list[2]) # 这里可能会出错!
age = int(str_list[3]) # 这里可能会出错!
if gender == '男':
bmr = (13.7 * weight) + (5.0 * height) - (6.8 * age) + 66
elif gender == '女':
bmr = (9.6 * weight) + (1.8 * height) - (4.7 * age) + 655
else:
bmr = -1
if bmr != -1:
print('您的性别:{},体重:{}公斤,身高:{}厘米,年龄:{}岁'.format(gender, weight, height, age))
print('您的基础代谢率:{}大卡'.format(bmr))
else:
print('暂不支持该性别')
except ValueError:
# 专门捕获 ValueError(例如:float('七十') 失败)
print('⚠️ 请输入正确的数字信息!')
except:
# 捕获所有其他未知错误
print('⚠️ 程序发生未知异常,请检查输入格式。')
print() # 输出空行
# 演示一次后,我们让程序退出循环
y_or_n = 'y'
main()请输入以下信息,用空格分割
用户输入的是:男 七十 175 25
⚠️ 请输入正确的数字信息!看!程序没有崩溃,而是友好地提示我们“请输入正确的数字信息!”。然后它正常地打印了一个空行,并准备进行下一次循环(在我们的例子里,我们直接让它退出了)。
💡 核心改动:我们只新增了 try...except 结构,就把程序的“抗揍”能力提升了一个等级。这就是“平滑引入新知识点”的魅力——只做一件事,但效果立竿见影。
第3步:应对更多“捣蛋”方式
用户可能不只是输错数字,还可能少输入信息,比如只输入了“男”,然后就回车了。这会导致 str_list[1] 根本不存在,引发 IndexError(索引错误)。
我们可以像添加 ValueError 一样,添加对 IndexError 的专门处理:
try:
# ... (尝试执行的代码)
except ValueError:
print('⚠️ 请输入正确的数字信息!')
except IndexError:
print('⚠️ 输入的信息不足,请按格式输入:性别 体重(kg) 身高(cm) 年龄')
except:
print('⚠️ 程序发生未知异常,请检查输入格式。')这样,程序就能针对不同的“捣蛋”方式,给出更精确的提示了!
四、为什么异常处理如此重要?
想象一下:
- 没有异常处理:用户输错 → 程序崩溃,红字刷屏 → 用户愤怒,可能再也不用了。
- 有异常处理:用户输错 → 程序提示“输入有误哦,请重试” → 用户觉得“这程序真智能,还提醒我”,欣然重试。
良好的异常处理是专业软件的标志。它不仅能提升用户体验,也能帮助开发者(也就是未来的你!)更快地定位和修复问题。在后续更复杂的项目中,它将是保证程序稳定运行的基石。
📝 动手练一练
【必做】体验“防弹衣”:将上面完整的4.0版本代码复制到你的编辑器中运行。然后,修改
input_str的值,分别测试以下几种“捣蛋”输入,观察程序的反应:'男 70 175 二十五'(年龄不是数字)'男 70'(信息不足)'Unknown 70 175 25'(性别不支持)'男 70 175 25 多余'(信息过多)
【挑战】自定义友好提示:现在的提示信息比较通用。请你修改
except块里的print语句,让提示变得更友好、更有趣,甚至带点“卖萌”属性。例如:“哎呀,体重好像输错了呢,要输入像70这样的数字哦~”
👉 点击查看第2题思路提示
思路:在 except 块中,你可以使用任何字符串。发挥你的创意!比如:
except ValueError:
print('(。•́︿•̀。) 看起来体重、身高或年龄中混入了文字,请检查后输入纯数字哦~')
except IndexError:
print('(´・ω・`)? 信息好像没填全呢,请按“性别 体重 身高 年龄”的格式填写,用空格分开。')记住,让程序有“人情味”,是吸引用户的一大法宝。
- 【回顾】模块化练习(来自视频课后练习):在3.0版本中,我们计算BMR的公式是直接写在主循环里的。请尝试将这部分计算逻辑封装成一个独立的函数,例如
calculate_bmr(gender, weight, height, age)。这会让你的代码结构更清晰,也是专业程序员的好习惯。
👉 点击查看第3题参考答案
思路:定义一个函数,接收性别、体重、身高、年龄四个参数,根据性别选择公式计算,并返回BMR值。
def calculate_bmr(gender, weight, height, age):
"""
根据性别、体重、身高、年龄计算基础代谢率(BMR)
参数: gender(字符串), weight(浮点数), height(浮点数), age(整数)
返回: BMR值(浮点数),如果性别不支持则返回-1
"""
if gender == '男':
return (13.7 * weight) + (5.0 * height) - (6.8 * age) + 66
elif gender == '女':
return (9.6 * weight) + (1.8 * height) - (4.7 * age) + 655
else:
return -1
# 测试一下这个函数
print(calculate_bmr('男', 70, 175, 25)) # 应输出一个计算后的数值
print(calculate_bmr('女', 60, 165, 30)) # 应输出一个计算后的数值
print(calculate_bmr('其他', 70, 175, 25)) # 应输出 -11730.0
1387.0
-1然后,你可以在主程序的 try 块中,用 bmr = calculate_bmr(gender, weight, height, age) 来调用这个函数,替换掉原来的if-else计算部分。
本章小结
恭喜你完成了《基础代谢率计算》这个项目的全部四个版本!让我们来回顾一下这条平滑而有趣的升级之路:
- 1.0 从零开始:我们认识了整数和浮点数,学会了用
type()查看类型,用int()/float()进行转换,做出了能计算单次BMR的程序。 - 2.0 持续交互:我们巩固了
while循环和if-else判断,让程序能够“不厌其烦”地一直为不同的用户服务。 - 3.0 善解人意:我们学习了字符串的
split()分割和format()格式化输出,让用户可以在一行内输入所有信息,并且输出结果带上单位,体验更佳。 - 4.0 坚固耐用(本节):我们引入了
try...except异常处理机制,为程序穿上了“防弹衣”,让它能优雅地处理用户的错误输入,不再轻易崩溃。
从处理一个数据(单次计算),到处理多次交互,再到处理一串信息(字符串分割),最后到处理意外情况,我们每一步都只学一个新东西,但组合起来,你已经做出了一个相当实用和健壮的小工具!
📋 行动清单
学完本章,你可以立刻:
- 运行你的4.0版本BMR计算器,并用家人或朋友的真实数据测试一下。
- 思考一下,你平时用的App或软件,在你输错时是怎么提示你的?尝试将那种友好的提示风格用到你的程序里。
- 准备好迎接下一个挑战——我们将告别处理“单个”或“几个”数据的时代,进入处理“一系列”数据的新篇章!
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载第4章代码包:基础代谢率计算(含全部版本 4 个 .py)ZIP · 3KB