问题:Python中异常处理程序的成本
在另一个问题中,可接受的答案建议用try / except块替换Python代码中的(非常便宜)if语句,以提高性能。
除了编码样式问题外,并假设永远不会触发异常,拥有一个异常处理程序与没有一个异常处理程序,与拥有与零比较的if语句相比,在性能方面有何不同?
回答 0
为什么不使用timeit
模块进行测量?这样,您可以查看它是否与您的应用程序相关。
好,所以我已经尝试了以下方法:
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 = {}\n{}".format(a,s))
print("%.2f usec/pass\n" % (1000000 * t.timeit(number=100000)/100000))
结果:
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
因此,正如预期的那样,没有任何异常处理程序会稍快一些(但在发生异常时会炸毁您的脸),并且只要不满足条件,它try/except
就会比显式的要快if
。
但这一切都在同一数量级内,并且无论哪种方式都不太重要。仅当实际满足条件时,if
版本才会明显更快。
回答 1
设计和历史常见问题解答中实际上回答了这个问题:
如果没有引发异常,则try / except块非常有效。实际上捕获异常是昂贵的。
回答 2
这个问题是误导的。如果您假设从未触发过该异常,那么这两个都不是最佳代码。
如果您假设异常是作为错误条件的一部分而触发的,那么您已经超出了想要最佳代码的范围(而且您可能始终无法像这样细粒度地对其进行处理)。
如果您将异常用作标准控制流程的一部分(这是Pythonic的“询问宽恕,而不是允许”的方式),那么异常将被触发,代价取决于异常的种类,如果,以及您估计发生异常的时间百分比。