简体   繁体   English

和vs多个ifs的Python效率

[英]Python efficiency of and vs multiple ifs

Is there an efficiency difference between using and in an if statement and using multiple if statements? 在if语句中使用和,以及在多个if语句中使用,效率之间存在差异吗? In other words, is something like 换句话说就是

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

different from an efficiency standpoint then: 从效率的角度来看,则:

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

My very basic testing does not reveal a difference, but does someone with more knowledge (or at least more thorough testing) have a definitive answer? 我最基本的测试并没有显示出差异,但是具有更多知识(或至少是更彻底的测试)的人是否有明确的答案?

This isn't enough of a performance difference, if any, to affect your decision. 这还不足以影响您的决策(如果有)。 IMO, the decision here should be made purely from a readability perspective. IMO,这里的决定应该纯粹从可读性的角度做出。 The first is generally more standard, I think, but there are situations when the second might be clearer. 我认为第一个通常更标准,但是在某些情况下第二个可能更清晰。 Choose the method that best gets your intent across. 选择最能传达您意图的方法。

Any differences in speed between using and and nested ifs will be minimal. 使用之间的速度的任何差别and与嵌套IFS将是最小的。 You are barking up the wrong tree. 您正在吠错树。 Consider this tree: 考虑这棵树:

if oftenTrueCondition and rarelyTrueCondition:

compared with 和....相比

if rarelyTrueCondition and oftenTrueCondition:

So, unless the first condition must be evaluated first (it is a guard to stop the next expression from crashing or doing something silly/expensive), consider swapping the order of evaluation. 因此,除非必须首先评估第一个条件(这是防止下一个表达式崩溃或做一些愚蠢/昂贵的事情的保护措施),否则请考虑交换评估顺序。

When in doubt, you can check what does python compile your statements in, using dis module: 如有疑问,可以使用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        

So as you can see, at python bytecode level, both statements are same - even while you use single if at first statement, it will do JUMP_IF_FALSE after first comparison. 如您所见,在python字节码级别上,两个语句都是相同的-即使在第一条语句中使用单条语句的情况下,在第一次比较后它也会执行JUMP_IF_FALSE。

无论哪种情况,在ifexpr1 == expr2计算结果都为false ,秒将不被评估。

The first one (one if with and ) is faster :-) 第一个( if使用and则更快):-)

I tried it out using timeit . 我使用timeit尝试。 These are the results: 结果如下:

Variant 1: 9.82836714316
Variant 2: 9.83886494559
Variant 1 (True): 9.66493159804
Variant 2 (True): 10.0392633241

For the last two, the first comparision is True , so the second one is skipped. 对于最后两个,第一个比较为True ,因此跳过第二个。 Interesting results. 有趣的结果。


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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM