多种异常与
安全除法函数
第十八天,我在昨天的 ValueError 基础上继续学习多种异常处理,让输入错误和除零错误分别进入对应分支,并补全 try / except / else / finally 的执行路线。
一个 try,处理两种不同异常
除法程序至少有两种常见错误:abc 无法转换成整数,会产生 ValueError;除数为 0 时,除法运算会产生 ZeroDivisionError。它们应该由不同的 except 分别处理。
try: # 尝试输入整数并进行除法
number1 = int(input("请输入第一个数字:")) # 转换第一个整数
number2 = int(input("请输入第二个数字:")) # 转换第二个整数
result = number1 / number2 # 除数为0时产生除零错误
print("计算结果:", result) # 没有异常时输出结果
except ValueError: # 接住整数转换错误
print("输入错误,请输入整数") # 显示类型错误提示
except ZeroDivisionError: # 接住除数为0的错误
print("计算错误,除数不能为0") # 显示除零错误提示
实际分别测试了 10 ÷ 2、abc 和 10 ÷ 0,得到 5.0、整数输入提示和除数不能为 0 的提示。输入 abc 后不会继续询问第二个数字,因为异常发生时会立即离开 try,跳到对应的 except。
加入循环:错误后重新输入
把异常结构放进 while True 后,发生错误时本轮代码执行完毕,自然进入下一轮;成功计算后才执行 break。因此两个 except 末尾不写 continue 也能重新询问。
break 的缩进位置很重要。如果把它放在 except ZeroDivisionError 下面,输入 0 后反而会立即结束循环。
try 后的 else
这里的 else 不需要手写判断条件。Python 会自动检查 try 是否完整执行:有异常时进入相应的 except,没有异常时跳过所有 except 并进入 else。
while True: # 不断尝试直到成功计算
try: # 尝试转换输入和进行除法
number1 = int(input("请输入第一个数字:")) # 获取第一个整数
number2 = int(input("请输入第二个数字:")) # 获取第二个整数
result = number1 / number2 # 尝试得到浮点数结果
except ValueError: # 输入转换失败时进入这里
print("输入错误,请输入整数") # 提示后开始下一轮
except ZeroDivisionError: # 除数为0时进入这里
print("计算错误,除数不能为0") # 提示后开始下一轮
else: # try没有异常时进入这里
print("计算结果:", result) # 输出成功结果
break # 成功后结束循环
同一次运行中依次输入 abc、10 ÷ 0 和 10 ÷ 4,前两次分别进入不同的异常分支,最后得到 2.5 并结束循环。
函数中使用 return 送出结果
安全除法被封装进 input_division() 后,成功路线改用 return result。它不仅结束循环和函数,还把结果交给外部的 answer;如果只使用 break,函数没有返回值,answer 会得到 None。
def input_division(): # 定义安全除法函数
while True: # 错误时持续重新询问
try: # 尝试转换输入和进行除法
number1 = int(input("请输入第一个数字:")) # 获取第一个整数
number2 = int(input("请输入第二个数字:")) # 获取第二个整数
result = number1 / number2 # 尝试计算浮点数结果
except ValueError: # 接住整数转换错误
print("输入错误,请输入整数") # 提示后继续循环
except ZeroDivisionError: # 接住除零错误
print("计算错误,除数不能为0") # 提示后继续循环
else: # 没有异常时进入这里
return result # 返回结果并结束函数
测试中先后触发了输入错误和除零错误,最后输入 9 与 2,函数返回 4.5,外部变量 answer 成功接住结果。
finally:每条路线最后都会经过
finally 无论是否发生异常都会执行。即使 else 中已经遇到 return result,Python 仍会先执行 finally,然后才把结果真正返回给外部。
else: # try没有异常时进入这里
return result # 准备把结果返回给外部
finally: # 成功或失败都会进入这里
print("本次输入处理结束") # 每一轮结束前都输出提示
最终测试依次经历文字输入、除数为 0 和有效除法。每次尝试后都输出“本次输入处理结束”;成功计算 10 ÷ 2 时,先执行 finally,再输出函数外的最终结果 5.0。
今天真正掌握的执行路线
ValueError:输入内容不能转换成需要的数值类型ZeroDivisionError:除法的除数为 0else:只在try没有异常时执行finally:正常完成、发生异常、遇到break或return时都会执行return:结束函数并把结果送给调用位置;break只能结束循环
今天不只是让程序“不报错”,而是开始区分错误类型:先判断发生了哪一种异常,再进入对应的处理路线。