ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用 Python 写一个简易计算器:从零讲清异常处理

用 Python 写一个简易计算器:从零讲清异常处理 为什么用计算器讲异常处理初学 Python 的学生写计算器第一版通常长这样afloat(input(第一个数))opinput(运算符)bfloat(input(第二个数))ifop:print(ab)elifop-:print(a-b)elifop*:print(a*b)elifop/:print(a/b) 这段代码能跑但一碰就碎。输入 abc 会崩除以 0 会崩运算符打错会静默什么都不输出。计算器是最适合讲异常处理的例子它的每一种错误都对应一个具体的、孩子能亲眼看到的崩溃现场不需要抽象地解释“什么是异常”。## 完整代码下面这版可以直接运行保存为 calc.py pythondefcalc(a,op,b):执行一次运算遇到问题抛出异常ifop:returnabifop-:returna-bifop*:returna*bifop/:ifb0:raiseZeroDivisionError(除数不能为 0)returna/braiseValueError(f不支持的运算符{op})defread_number(prompt):反复要求输入直到拿到一个合法数字whileTrue:textinput(prompt).strip()try:returnfloat(text)exceptValueError:print(f {text} 不是数字请重新输入)defmain():print(简易计算器输入 q 退出)whileTrue:firstinput(\n第一个数或 q 退出).strip()iffirst.lower()q:print(已退出)breaktry:afloat(first)exceptValueError:print(f {first} 不是数字请重新输入)continueopinput(运算符 - * /).strip()bread_number(第二个数)try:resultcalc(a,op,b)exceptZeroDivisionErrorase:print(f 计算失败{e})exceptValueErrorase:print(f 计算失败{e})else:print(f 结果{a}{op}{b}{result})if__name____main__:main()## 代码要点拆解**1.把运算逻辑和输入输出分开。**calc() 只负责算不负责打印、不负责读输入。这样做的好处是异常有明确的“抛出点”参数不对calc() 直接 raise调用者必须处理。如果运算和输入揉在一个函数里异常到底该在哪一层捕获就说不清了。**2.主动 raise 比被动崩溃更好。**1/0 本身就会抛 ZeroDivisionError但代码里仍然显式写了一遍 pythonifb0:raiseZeroDivisionError(除数不能为 0) 目的是把“除数为0是非法输入”这个业务规则写进代码里。Python 默认的报错信息是 division by zero而这里换成中文提示面向用户更友好。学生也能借此理解raise 就是自己造一个异常。**3.try/except/else 的 else 分支。**很多教材只讲 try 和 except。这里的 else 表示“try 里没有出错才执行”把打印结果的代码放进去语义上比全塞在 try 里更清晰try 块只放可能出错的那一行。**4.read_number() 里的 whileTruetry。**这是输入校验最经典的写法拿到合法值就 return 跳出循环不合法就打印提示继续循环。比套两层 if 判断字符串格式要简洁得多。## 学生常见错误**错误一用 except: 一把抓。**pythontry:resulta/bexcept:print(出错了) 裸 except 会吞掉所有异常包括 KeyboardInterruptCtrlC程序可能变得无法中断调试时也看不到真实错误位置。至少要写成 exceptZeroDivisionError:捕获自己预期的那一种。**错误二把整个 main 包进一个 try。**pythontry:afloat(input())bfloat(input())print(a/b)exceptValueError:print(输入错误)exceptZeroDivisionError:print(除数为零) 逻辑上能跑但一旦出错就无法判断是第一个数错了还是第二个数错了用户只能从头再来。异常处理的范围要尽量小精准到具体那一行。**错误三认为 float(1e3) 会报错。**它不会float 支持科学计数法结果是 1000.0。同理 float(inf)、float(nan) 也是合法的。如果作业要求“只接受普通数字”需要额外判断 math.isfinite()这一点可以留作拓展。**错误四continue 和 break 用混。**在 main 的第一个数校验里输入非法必须 continue否则会继续往下执行 input(运算符)把一次错误输入变成两次提问。建议让学生自己在纸上画出循环走向。## 可以留的练习1.增加 ** 幂运算和 % 取余注意 0**-1 也会抛 ZeroDivisionError验证一下。2.2.把 main 的两个 except 合并成 except(ZeroDivisionError,ValueError)ase:观察行为是否一致。3.3.增加 finally 分支在每次循环结束时打印一行分隔线理解 finally 的执行时机。4.4.让 calc() 支持字符串表达式如 12用 split() 拆分拆分失败时抛自定义异常。## 小结异常处理不是“加个try就完事”它包含三个判断哪里可能出错、出错后谁能处理、处理后是继续还是退出。计算器项目小但把 raise、try/except/else、whileTrue 输入循环、异常捕获范围这几个点全串起来了。让学生先写崩溃版再一步步改到健壮版比直接给完整代码更能记住每种异常对应的现场。
返回列表