Cost of exception handlers in Python
在另一个问题中,公认的答案建议用try/except块替换python代码中的if语句(非常便宜),以提高性能。
撇开编码风格的问题不谈,假设从未触发异常,使用异常处理程序与不使用异常处理程序、使用比较为零的if语句有多大区别?
为什么不使用
好的,所以我尝试了以下方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import timeit statements=["""\ try: b = 10/a except ZeroDivisionError: pass""", """\ if a: b = 10/a""", "b = 10/a"] for a in (1,0): for s in statements: t = timeit.Timer(stmt=s, setup='a={}'.format(a)) print("a = {} {}".format(a,s)) print("%.2f usec/pass " % (1000000 * t.timeit(number=100000)/100000)) |
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | a = 1 try: b = 10/a except ZeroDivisionError: pass 0.25 usec/pass a = 1 if a: b = 10/a 0.29 usec/pass a = 1 b = 10/a 0.22 usec/pass a = 0 try: b = 10/a except ZeroDivisionError: pass 0.57 usec/pass a = 0 if a: b = 10/a 0.04 usec/pass a = 0 b = 10/a ZeroDivisionError: int division or modulo by zero |
因此,正如预期的那样,没有任何异常处理程序的速度稍微快一点(但在异常发生时会在您的脸上爆炸),并且只要不满足条件,
但它们都在同一数量级内,不太可能以任何方式发生关系。只有在实际满足条件的情况下,
这个问题实际上在设计和历史常见问题解答中得到了解答:
A try/except block is extremely efficient if no exceptions are raised.
Actually catching an exception is expensive.
这个问题有误导性。如果假设从未触发过异常,那么这两种情况都不是最佳代码。
如果假设异常是作为错误条件的一部分触发的,那么您已经超出了需要最佳代码的范围(而且您可能不会在这样的细粒度级别处理它)。
如果你将异常作为标准控制流程的一部分使用——这就是Python式的"请求原谅,而不是许可"方式——那么异常将被触发,并且成本取决于异常的类型、if的类型以及你估计异常发生的时间百分比。