我们并不能预估一个代码块到底会不会抛出异常,以及抛出多少种异常。所以需要使用try…except语句捕捉尽可能多的异常,因此except子句可以包含任意多个。不过程序员并不能准确估计一个代码块抛出的异常种类,所以使用具体异常类来捕捉异常,有可能会遗漏某个异常,在这种情况下,当抛出这个被遗漏的异常后,程序还是会崩溃,所以比较保险的做法是最后一个except子句不使用任何异常类,这样就会捕捉其他所有未指定的异常。
try:
....
except 异常类1:
....
except 异常类2:
....
....
except 异常类n:
....
except: # 捕捉其他未指定的异常
....
[例 9.3] 本例通过specialcalc类的三个方法(add、sub和mul)和raise语句抛出了两个自定义的异常(NegativeException和ZeroException),div方法可能会抛出内建ZeroException异常。这三个异常分别通过三个except子句捕捉。最后使用except子句捕捉其他未指定的异常。本例的核心逻辑代码在while循环中,通过console输入表达式(如add(4,2)),动态调用specialcalc类的相应方法,不管是抛出异常,还是正常调用,都会重新要求输入新的表达式,知道输入"exit"命令退出while循环。
# 自定义异常类,表示操作数或计算结果为负数时抛出的异常
class NegativeException(Exception):
pass
# 自定义异常类,表示操作数为0时抛出的异常
class ZeroException(Exception):
pass
class specialcalc:
def add(self,x,y):
# 当x和y至少有一个小于0时抛出NegativeException异常
if x < 0 or y < 0:
raise NegativeException
return x + y
def sub(self,x,y):
# 当x和y的差值是负数时抛出NegativeException异常
if x - y < 0:
raise NegativeException
return x - y
def mul(self,x,y):
# 当x和y至少有一个值为0时抛出ZeroException异常
if x == 0 or y == 0:
raise ZeroException
return x * y
def div(self,x,y):
return x / y
while True:
try:
# 创建specialcalc类的实例
calc = specialcalc()
# 从console输出表达式
expr = input('请输入要计算的表达式,例如,add(1,2):')
# 当输入"exit"时退出循环
if expr == 'exit':
break;
# 使用eval函数动态执行输入的表达式,前面需要加上"calc."前缀,因为这些方法都属于specialcalc类
result = eval('calc.' + expr)
# 输出计算结果,保留小数点后两位
print('计算结果:{:.2f}'.format(result))
except NegativeException: # 捕捉NegativeException异常
print('******负数异常******')
except ZeroException: # 捕捉ZeroException异常
print('******操作数为0异常******')
except ZeroDivisionError: # 捕捉ZeroDivisionError异常
print('******分母不能为0******')
except:
print('******其他异常******')
输出结果:
请输入要计算的表达式,例如,add(1,2):add(4,65.3)
计算结果:69.30
请输入要计算的表达式,例如,add(1,2):add(-5,2)
******负数异常******
请输入要计算的表达式,例如,add(1,2):sub(4,6)
******负数异常******
请输入要计算的表达式,例如,add(1,2):mul(45,0)
******操作数为0异常******
请输入要计算的表达式,例如,add(1,2):div(40,0)
******分母不能为0******
请输入要计算的表达式,例如,add(1,2):div(54,34.1)
计算结果:1.58
请输入要计算的表达式,例如,add(1,2):abcd
******其他异常******
请输入要计算的表达式,例如,add(1,2):exit
在输入表达式的过程中,最后输入了一个abcd,很明显,输入的内容并不是正确的表达式,而且抛出的异常并没有使用except子句明确指定,因此,最后的except子句会捕捉这个异常。