不用try也可以优雅的处理异常
Pythonista[1]们都知道使用 try 和 except 来处理可能发生的异常,当异常发生时执行我们预先编写好的代码块。
但是常碰到的情形是这样的:
我们知道这个异常有可能发生 我们不关心这个异常,如果发生了,什么也不用处理,直接忽略就好
如果要处理这种情形的异常,那么不必使用 try-except,Python 内置的 contextlib 库提供了一个函数,叫 suppress,是处理这种异常更优雅的方式,Pythonista 一定要尝试使用。
假如我们要对一系列数字的倒数求和,这些数字可能会出现 0,因此需要处理异常,通常情况下,如果使用 try 和 except 会是这样的:
nums = [3,0,3,0,3]
result = 0
for num in nums:
try:
result += 1/num
except ZeroDivisionError:
pass
print(result) # 1.0
这里,我们捕捉了 ZeroDivisionError
异常并忽略,最终得到数字的倒数的和为 1.0。
假如我们使用 contextlib 库提供的 suppress,代码就是这样的:
from contextlib import suppress
nums = [3,0,3,0,3]
result = 0
for num in nums:
with suppress(ZeroDivisionError):
result += 1/num
print(result) # 1.0
从形式上看,suppress 的代码行数更少,看来也更优雅,更易于阅读理解。
有人会说了,我使用下面的方法一行就搞定了:
result = sum([1/x for x in nums if x != 0])
这当然是完全正确的,上述只是以这个为例子说明下 suppress 的用法,不过当异常类型增多的时候,上述的方法也有弊端,比如数字除了不能为 0,也不能为字符串的情况, 那么就需要写成这样:
nums = [3,0,3,0,3,'3'] #有字符串,也需要忽略
result = sum([1/x for x in nums if x != 0 and type(x) == int])
当异常的情况不断增多,这种写法就很难看了,而使用 suppress,只需要这样:
for num in nums:
with suppress(ZeroDivisionError, TypeError):
result += 1/num
甚至,你想忽略所有的异常,只需要给 suppress 传入异常类的基础类 Exception 即可:
for num in nums:
with suppress(Exception):
result += 1/num
需要注意的是,不要这样写
result = 0
nums = [3,0,3,0,3]
with suppress(Exception):
for num in nums:
result += 1/num
print(result) # 0.3333333333333333
如果 suppress 写在了循环体的外面,当发生异常时,后面的循环操作将会被 break,因此这种情况下,结果是 0.333333,原因就是第二个数是 0 引发的异常,这个异常虽然被忽略,但后面的循环也停止了。这一点不是 suppress 特有的,你把 try 放循环外面也是一样的:
result = 0
nums = [3,0,3,0,3]
try:
for num in nums:
result += 1/num
except Exception:
pass
print(result) # 0.3333333333333333
本文介绍一种更加优雅的异常处理方法,就是 Python 标准库 contextlib 的函数 suppress 它更加优雅和容易理解。如果觉得本文对你有所帮助,关注、转发、在看,一条龙走起,我就当你打赏了 66 元了,感谢老铁。
往期 Python 编程技巧文章推荐
参考资料
Pythonista: 表示「Python支持者」,更表示资深的,对代码质量和品味有要求的开发者,这种执念也就是所谓「Pythonic」