python中最好的方法是什么:if语句中的多个OR 或 IN ?考虑性能和最佳实践。
if cond == '1' or cond == '2' or cond == '3' or cond == '4' (etc...) :
OR
if cond in ['1','2','3','4']:
谢谢。
答案 0 :(得分:15)
最好的方法是使用 set :
if cond in {'1','2','3','4'}:
因为集合中的成员资格测试是O(1)(不变成本)。
其他两种方法的复杂程度相同;仅仅是不变成本的差异。列表上的in
测试和or
链短路;找到匹配后立即终止。一个使用一系列字节码跳转(如果True
则跳转到结尾),另一个使用C循环,如果值匹配则使用提前退出。在最糟糕的情况下,cond
}。在这两个中,我会在任何一天选择False
测试,因为它更具可读性。
答案 1 :(得分:3)
在大多数情况下,Pieters的答案是最好的。但是,在您的具体情况下,我不会使用in
或or
,而是执行此操作:
if 0 < int(cond) < 5:
如果cond为'1','2','3'或'4',则if块将运行。关于这一点的好处是它比其他答案短。
答案 2 :(得分:2)
这实际上取决于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 中,字节码支持set constants;那里的代码评估为:
>>> 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