Python效率和vs多个ifs

时间:2010-08-20 17:29:01

标签: python performance conditional

在if语句中使用和使用多个if语句之间是否存在效率差异?换句话说,就像是

if expr1 == expr2 and expr3==expr4:
  dostuff()

与效率的观点不同:

if expr1 == expr2:
  if expr3 == expr4:
    dostuff()

我的基本测试并没有发现差异,但有更多知识(或至少更彻底的测试)的人是否有明确的答案?

5 个答案:

答案 0 :(得分:14)

这不足以影响您的决定的性能差异(如果有的话)。 IMO,这里的决定应该纯粹从可读性的角度出发。我认为第一个通常更标准,但有些情况下第二个可能更清晰。选择最能实现您意图的方法。

答案 1 :(得分:11)

使用and和嵌套ifs之间的速度差异将是最小的。你正在咆哮错误的树。考虑这棵树:

if oftenTrueCondition and rarelyTrueCondition:

比较
if rarelyTrueCondition and oftenTrueCondition:

因此,除非必须首先评估第一个条件(防止下一个表达式崩溃或做一些愚蠢/昂贵的事情),否则请考虑交换评估顺序。

答案 2 :(得分:4)

在任何一种情况下,expr1 == expr2评估为false中的if,第二项不会被评估。

答案 3 :(得分:4)

如果有疑问,可以使用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字节码级别,两个语句都是相同的 - 即使在第一个语句中使用single if时,它也会在第一次比较后执行JUMP_IF_FALSE。

答案 4 :(得分:2)

第一个(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)