Catching exceptions is expensive, but exceptions should be exceptional (read, not happen very often). If exceptions are rare, try/catch
is faster than LBYL.
The following example times a dictionary key lookup using exceptions and LBYL when the key exists and when it doesn't exist:
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()))
Output
Run 1 = 0.05600167960596991 # try/catch, key exists
Run 2 = 0.08530091918578364 # LBYL, key exists (slower)
Run 3 = 0.3486251291120652 # try/catch, key doesn't exist (MUCH slower)
Run 4 = 0.050621117060586585 # LBYL, key doesn't exist
When the usual case is no exception, try/catch
is "extremely efficient" when compared to LBYL.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…