Python常见问题解答:“异常有多快?”

2024-04-19 18:46:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我只是在看Python的FAQ,因为它是在另一个问题中提到的。我以前从来没有仔细研究过它,我遇到了this question:“异常有多快?“:

A try/except block is extremely efficient. Actually catching an exception is expensive. In versions of Python prior to 2.0 it was common to use this idiom:

try:
    value = mydict[key]
except KeyError:
    mydict[key] = getvalue(key)
    value = mydict[key]

我有点惊讶于“捕捉异常是昂贵的”部分。这是否仅指那些实际将异常保存在变量中的except情况,或者通常是所有except(包括上例中的那个)?在

我一直认为使用如图所示的这样的习语是非常愚蠢的,尤其是在Python中,“请求原谅比获得许可更容易”。也有很多答案都遵循这个想法。在

捕捉异常的性能真的那么差吗?在这种情况下,人们是否应该效仿LBYL(“三思而后行”?在

(请注意,我并不是直接谈论常见问题解答中的示例;还有许多其他示例中,您只需查找异常而不是检查之前的类型。)


Tags: tokey示例isvalue情况thisblock
3条回答

如果找不到密钥的情况非常特殊,我建议使用“get”方法,它在所有情况下都提供恒定的速度:

s.append('''\
x = D.get('key', None)
''')

s.append('''\
x = D.get('xxx', None)
''')

显然,成本取决于实施情况,但我不担心。不管怎样,这不太可能有什么关系。标准协议会在最奇怪的地方引发异常(想想StopIteration),所以无论您是否喜欢,您都会被引发和捕获包围。在

在LBYL和EAFP之间进行选择时,要担心代码的可读性,而不是关注微优化。如果可能的话,我会避免类型检查,因为这可能会降低代码的通用性。在

捕获异常的代价是昂贵的,但是异常应该是异常的(读,不经常发生)。如果异常很少,try/catch比LBYL快。在

下面的示例在键存在和不存在时使用异常和LBYL计算字典键查找的次数:

import timeit

s = []

s.append('''\
try:
    x = D['key']
except KeyError:
    x = None
''')

s.append('''\
x = D['key'] if 'key' in D else None
''')

s.append('''\
try:
    x = D['xxx']
except KeyError:
    x = None
''')

s.append('''\
x = D['xxx'] if 'xxx' in D else None
''')

for i,c in enumerate(s,1):
    t = timeit.Timer(c,"D={'key':'value'}")
    print('Run',i,'=',min(t.repeat()))

输出

^{pr2}$

通常情况下也不例外,try/catch与LBYL相比“非常有效”。在

相关问题 更多 >