読みやすさについて説明するだけでなく、一部のシナリオではパフォーマンスも重要だと思います。クイックタイムイットベンチマークは、テスト(つまり「許可を求める」)が実際には例外を処理する(つまり「許しを求める」)よりもわずかに速いことを示しています。
ベンチマークを設定するコードは次のとおりです。ランダムなキーと値のペアの大きな辞書を生成します。
setup = """
import random, string
d = {"".join(random.choices(string.ascii_letters, k=3)): "".join(random.choices(string.ascii_letters, k=3)) for _ in range(10000)}
"""
次に、if
テスト:
stmt1 = """
key = "".join(random.choices(string.ascii_letters, k=3))
if key in d:
_ = d[key]
"""
私たちに与える:
>>> timeit.timeit(stmt=stmt1, setup=setup, number=1000000)
1.6444563979999884
一方、例外を利用したアプローチ
stmt2 = """
key = "".join(random.choices(string.ascii_letters, k=3))
try:
_ = d[key]
except KeyError:
pass
"""
私たちに与える:
>>> timeit.timeit(stmt=stmt2, setup=setup, number=1000000)
1.8868465850000575
興味深いことに、実際のベンチマークからセットアップに世代を引き上げ、それによって同じkey
キーを何度も探して、非常に異なる数を提供します。
>>> timeit.timeit(stmt=stmt1, setup=setup, number=100000000)
2.3290171539999847
>>> timeit.timeit(stmt=stmt2, setup=setup, number=100000000)
26.412447488999987
これがテストと例外処理の利点を強調するのか、それとも辞書が前回のルックアップの結果をバッファリングしてベンチマーク結果をテストに偏らせるのかを推測したくありません…