引发异常
现在,你已经充分了解了回溯和处理异常,接下来让我们了解引发异常。
你可能已经了解了在编写代码时可能会导致错误的情况。 在这些情况下,引发异常很有用,可以让其他代码能够认识到该问题。
引发异常还有助于对其他代码进行决策。 如前面所示,根据错误,代码可以做出明智的决策,以解决、绕开或忽略问题。
宇航员将其用水量限制为每日大约 11 升。 让我们创建一个函数,该函数根据宇航员的数目,可以计算一天或更长时间后剩余的水量:
def water_left(astronauts, water_left, days_left):
daily_usage = astronauts * 11
total_usage = daily_usage * days_left
total_water_left = water_left - total_usage
return f"Total water left after {days_left} days is: {total_water_left} liters"
试运行该函数,其中宇航员为 5 名,剩余水量 100 升,行程时间为 2 日:
water_left(5, 100, 2)
'Total water left after 2 days is: -10 liters'
这并不是很有用,因为水量的减少应该是一个错误。 然后,导航系统会提醒宇航员,两天后所有人都没有足够的剩余水量。 如果你是一位设计导航系统的工程师,你可能会在 water_left()
函数中引发异常,以提醒错误情况:
def water_left(astronauts, water_left, days_left):
daily_usage = astronauts * 11
total_usage = daily_usage * days_left
total_water_left = water_left - total_usage
if total_water_left < 0:
raise RuntimeError(f"There is not enough water for {astronauts} astronauts after {days_left} days!")
return f"Total water left after {days_left} days is: {total_water_left} liters"
现在再次运行:
water_left(5, 100, 2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in water_left
RuntimeError: There is not enough water for 5 astronauts after 2 days!
在导航系统中,发出警报信号的代码现在可以使用 RuntimeError
发出警报:
try:
water_left(5, 100, 2)
except RuntimeError as err:
alert_navigation_system(err)
water_left()
函数还可以更新以防止传递不受支持的类型。 尝试传递非整数的参数以检查错误输出:
water_left("3", "200", None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in water_left
TypeError: can't multiply sequence by non-int of type 'NoneType'
TypeError
中的错误在该函数预期的上下文中不太易懂。 更新函数,使其使用 TypeError
,但提供更优化的消息:
def water_left(astronauts, water_left, days_left):
for argument in [astronauts, water_left, days_left]:
try:
# If argument is an int, the following operation will work
argument / 10
except TypeError:
# TypeError will be raised only if it isn't the right type
# Raise the same exception but with a better error message
raise TypeError(f"All arguments must be of type int, but received: '{argument}'")
daily_usage = astronauts * 11
total_usage = daily_usage * days_left
total_water_left = water_left - total_usage
if total_water_left < 0:
raise RuntimeError(f"There is not enough water for {astronauts} astronauts after {days_left} days!")
return f"Total water left after {days_left} days is: {total_water_left} liters"
现在重试以获得优化错误:
water_left("3", "200", None)
Traceback (most recent call last):
File "<stdin>", line 5, in water_left
TypeError: unsupported operand type(s) for /: 'str' and 'int'
During handling of the preceding exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in water_left
TypeError: All arguments must be of type int, but received: '3'