Pythonでの最良のアプローチは何ですか: ifステートメントでの複数のORまたはIN ? パフォーマンスとベスト プラクティスを考慮します。
if cond == '1' or cond == '2' or cond == '3' or cond == '4': pass
また
if cond in ['1','2','3','4']: pass
Pythonでの最良のアプローチは何ですか: ifステートメントでの複数のORまたはIN ? パフォーマンスとベスト プラクティスを考慮します。
if cond == '1' or cond == '2' or cond == '3' or cond == '4': pass
また
if cond in ['1','2','3','4']: pass
最良のアプローチはsetを使用することです:
if cond in {'1','2','3','4'}:
セット内のメンバーシップ テストは O(1) (一定コスト) であるため。
他の 2 つのアプローチの複雑さは同じです。固定費の差に過ぎません。in
リストのテストとor
チェーンの短絡の両方。一致が見つかるとすぐに終了します。1 つは一連のバイトコード ジャンプ ( の場合は末尾にジャンプTrue
) を使用し、もう 1 つは C ループを使用し、値が一致する場合は早期終了します。最悪のシナリオでは、 whereがシーケンス内の要素と一致しない場合、どちらのアプローチでも、 を返す前にすべての要素をチェックするcond
必要がありますFalse
。2 つのうち、私はin
いつでもこのテストを選びます。
これは実際には Python のバージョンに依存します。Python 2.7では、バイトコードにセット定数がありませんでした。したがって、Python 2 では、固定定数の場合、値の小さなセットはタプルを使用します。
if x in ('2', '3', '5', '7'):
...
タプルは定数です:
>>> dis.dis(lambda: item in ('1','2','3','4'))
1 0 LOAD_GLOBAL 0 (item)
3 LOAD_CONST 5 (('1', '2', '3', '4'))
6 COMPARE_OP 6 (in)
9 RETURN_VALUE
Python は、Python 2.7 の定数リストをタプルに最適化するのにも十分スマートです。
>>> dis.dis(lambda: item in ['1','2','3','4'])
1 0 LOAD_GLOBAL 0 (item)
3 LOAD_CONST 5 (('1', '2', '3', '4'))
6 COMPARE_OP 6 (in)
9 RETURN_VALUE
しかし、Python 2.7 バイトコード (およびコンパイラ) は定数セットをサポートしていません。
>>> dis.dis(lambda: item in {'1','2','3','4'})
1 0 LOAD_GLOBAL 0 (item)
3 LOAD_CONST 1 ('1')
6 LOAD_CONST 2 ('2')
9 LOAD_CONST 3 ('3')
12 LOAD_CONST 4 ('4')
15 BUILD_SET 4
18 COMPARE_OP 6 (in)
21 RETURN_VALUE
これは、テストif
ごとにセットイン状態を再構築する必要があることを意味します。
ただし、Python 3.4では、バイトコードは定数の設定をサポートしています。コードは次のように評価されます。
>>> dis.dis(lambda: item in {'1','2','3','4'})
1 0 LOAD_GLOBAL 0 (item)
3 LOAD_CONST 5 (frozenset({'4', '2', '1', '3'}))
6 COMPARE_OP 6 (in)
9 RETURN_VALUE
マルチor
コードに関しては、完全に恐ろしいバイトコードを生成します。
>>> dis.dis(lambda: item == '1' or item == '2' or item == '3' or item == '4')
1 0 LOAD_GLOBAL 0 (item)
3 LOAD_CONST 1 ('1')
6 COMPARE_OP 2 (==)
9 JUMP_IF_TRUE_OR_POP 45
12 LOAD_GLOBAL 0 (item)
15 LOAD_CONST 2 ('2')
18 COMPARE_OP 2 (==)
21 JUMP_IF_TRUE_OR_POP 45
24 LOAD_GLOBAL 0 (item)
27 LOAD_CONST 3 ('3')
30 COMPARE_OP 2 (==)
33 JUMP_IF_TRUE_OR_POP 45
36 LOAD_GLOBAL 0 (item)
39 LOAD_CONST 4 ('4')
42 COMPARE_OP 2 (==)
>> 45 RETURN_VALUE
ほとんどの場合、Pieters の回答が最適です。ただし、特定のケースでは、in
orは使用しませんor
が、代わりにこれを行います。
if 0 < int(cond) < 5:
cond が '1'、'2'、'3'、または '4' の場合、if ブロックが実行されます。これの良いところは、他の回答よりも短いことです。