Python FAQ:「例外はどれほど速いのですか?」

私は別の質問で言及されているので、Python
FAQを見ていただけです。これまでのところ詳細を見たことはありませんでしたが、この質問:「例外はどのくらい速いのですか?」:

try/exceptブロックは非常に効率的です。実際に例外をキャッチするのは高価です。
2.0より前のバージョンのPythonでは、このイディオムを使用するのが一般的でした:

  try:
    値= mydict [キー]
KeyErrorを除く:
    mydict [key] = getvalue(key)
    値= mydict [キー]
 

「例外をキャッチするのは高価です」の部分についてちょっと驚きました。これは実際に例外を変数に保存する場合、または一般的にすべての
except (上記の例を含む)の場合を除いて、これらの except

私は常に、このようなイディオムを使用することは、特にPython “許しを得るのが許諾を得るのが簡単です”
のように非常に非常態であると思っていました。 SOに関する多くの答えも、一般にこの考え方に従います。

例外をキャッチするためのパフォーマンスは本当に悪いですか?このような場合、LBYL(「飛び越す前に見てください」)に従うべきでしょうか?

(私はFAQの例について直接言及しているわけではありませんが、これまでに型を調べる代わりに例外を調べる例がたくさんあります)。

ベストアンサー

例外をキャッチするのは高価ですが、例外は例外的(読んでも頻繁ではありません)にする必要があります。例外がまれである場合、
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()))

出力

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

通常の場合も例外ではなく、 try/catch はLBYLと比較して “非常に効率的”です。

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です