在if语句中使用“&&”和使用多个if语句之间是否存在效率差异?换句话说,类似于以下代码:
if expr1 == expr2 and expr3==expr4:
dostuff()
从效率的角度来看,与...不同:
if expr1 == expr2:
if expr3 == expr4:
dostuff()
我进行的基本测试没有发现差异,但是有更多知识(或至少更彻底的测试)的人有一个确定的答案吗?
在if语句中使用“&&”和使用多个if语句之间是否存在效率差异?换句话说,类似于以下代码:
if expr1 == expr2 and expr3==expr4:
dostuff()
从效率的角度来看,与...不同:
if expr1 == expr2:
if expr3 == expr4:
dostuff()
我进行的基本测试没有发现差异,但是有更多知识(或至少更彻底的测试)的人有一个确定的答案吗?
使用 and
和嵌套的 if 之间的速度差异将是很小的。你可能在抓错了树。考虑一下这棵树:
if oftenTrueCondition and rarelyTrueCondition:
相比之下
if rarelyTrueCondition and oftenTrueCondition:
因此,除非第一个条件必须首先评估(它是防止下一个表达式崩溃或执行愚蠢/昂贵操作的保护条件),否则请考虑交换评估顺序。
在性能方面没有太大差异,如果有的话,这不足以影响您的决定。在我看来,这里的决策应该纯粹从易读性的角度出发。第一种方法通常更标准,但有时第二种方法可能会更清晰。选择最能表达您意图的方法。
expr1 == expr2
在 if
中都会被评估为 false
,因此第二个表达式不会被评估。当你有疑问时,你可以使用dis模块检查Python编译你的语句的方式:
>>> import dis
>>> def test1():
... if expr1 == expr2 and expr3==expr4:
... dostuff()
...
>>> def test2():
... if expr1 == expr2:
... if expr3 == expr4:
... dostuff()
...
>>> dis.dis(test1)
2 0 LOAD_GLOBAL 0 (expr1)
3 LOAD_GLOBAL 1 (expr2)
6 COMPARE_OP 2 (==)
9 JUMP_IF_FALSE 24 (to 36)
12 POP_TOP
13 LOAD_GLOBAL 2 (expr3)
16 LOAD_GLOBAL 3 (expr4)
19 COMPARE_OP 2 (==)
22 JUMP_IF_FALSE 11 (to 36)
25 POP_TOP
3 26 LOAD_GLOBAL 4 (dostuff)
29 CALL_FUNCTION 0
32 POP_TOP
33 JUMP_FORWARD 1 (to 37)
>> 36 POP_TOP
>> 37 LOAD_CONST 0 (None)
40 RETURN_VALUE
>>> dis.dis(test2)
2 0 LOAD_GLOBAL 0 (expr1)
3 LOAD_GLOBAL 1 (expr2)
6 COMPARE_OP 2 (==)
9 JUMP_IF_FALSE 28 (to 40)
12 POP_TOP
3 13 LOAD_GLOBAL 2 (expr3)
16 LOAD_GLOBAL 3 (expr4)
19 COMPARE_OP 2 (==)
22 JUMP_IF_FALSE 11 (to 36)
25 POP_TOP
4 26 LOAD_GLOBAL 4 (dostuff)
29 CALL_FUNCTION 0
32 POP_TOP
33 JUMP_ABSOLUTE 41
>> 36 POP_TOP
37 JUMP_FORWARD 1 (to 41)
>> 40 POP_TOP
>> 41 LOAD_CONST 0 (None)
44 RETURN_VALUE
如您所见,在Python字节码级别上,这两个语句是相同的 - 即使在第一个语句中使用单个if,它也会在第一次比较后执行JUMP_IF_FALSE。
第一个方法(使用if
和and
)更快 :-)
我用timeit
测试了一下,结果如下:
Variant 1: 9.82836714316
Variant 2: 9.83886494559
Variant 1 (True): 9.66493159804
Variant 2 (True): 10.0392633241
对于最后两个,第一个比较是True
,所以第二个被跳过了。有趣的结果。
import timeit
print "Variant 1: %s" % timeit.timeit("""
for i in xrange(1000):
if i == 2*i and i == 3*i:
pass
""",
number = 1000)
print "Variant 2: %s" % timeit.timeit("""
for i in xrange(1000):
if i == 2*i:
if i == 3*i:
pass
""",
number = 1000)
print "Variant 1 (True): %s" % timeit.timeit("""
for i in xrange(1000):
if i == i and i == 3*i:
pass
""",
number = 1000)
print "Variant 2 (True): %s" % timeit.timeit("""
for i in xrange(1000):
if i == i:
if i == 3*i:
pass
""",
number = 1000)
if
语句更清晰明了,那就按照你认为合理的方式去做。 - derekerdmannand
,所以短路计算在这两种方法之间有什么区别呢?在嵌套的if
中,如果第一个条件为假,则不会检查其他条件。短路计算也是如此。 - Astitva Srivastava