复合if语句更快,还是多个if语句?

时间:2014-03-10 01:51:10

标签: python python-3.x

假设我们有两段代码:

if foo == True and bar == False and baz == True:
    do something

if foo == True:
    if bar == False:
        if baz == True:
            do something

哪个更快?

2 个答案:

答案 0 :(得分:6)

在我的机器上使用IPython

In [1]: foo = True
In [2]: bar = False
In [3]: baz = True

In [4]: %%timeit
   ...: if foo and not bar and baz:
   ...:     lambda: None
1000000 loops, best of 3: 265 ns per loop

In [5]: %%timeit
   ...: if foo:
   ...:   if not bar:
   ...:     if baz:
   ...:       lambda: None
1000000 loops, best of 3: 275 ns per loop

如果将它拆分,看起来有10英寸的开销。如果10ns很重要,你应该使用另一种语言。

因此,出于所有实际目的,不,没有区别。

如果我们看得更深一些,我们可以看到这个微小的差异来自哪里。

In [6]: def compound():
   ...:     if foo and not bar and baz:
   ...:         lambda: None
In [7]: def multiple():
   ....:     if foo:
   ....:         if not bar:
   ....:             if baz:
   ....:                 lambda: None

In [8]: import dis
In [9]: dis.dis(compound)
  2           0 LOAD_GLOBAL              0 (foo)
              3 POP_JUMP_IF_FALSE       29
              6 LOAD_GLOBAL              1 (bar)
              9 UNARY_NOT           
             10 POP_JUMP_IF_FALSE       29
             13 LOAD_GLOBAL              2 (baz)
             16 POP_JUMP_IF_FALSE       29

  3          19 LOAD_CONST               1 (<code object <lambda> at 0x101d953b0, file "<ipython-input-9-d057c552d038>", line 3>)
             22 MAKE_FUNCTION            0
             25 POP_TOP             
             26 JUMP_FORWARD             0 (to 29)
        >>   29 LOAD_CONST               0 (None)
             32 RETURN_VALUE   

这有13条指令

In [15]: dis.dis(g)
  2           0 LOAD_GLOBAL              0 (foo)
              3 POP_JUMP_IF_FALSE       34

  3           6 LOAD_GLOBAL              1 (bar)
              9 POP_JUMP_IF_TRUE        34

  4          12 LOAD_GLOBAL              2 (baz)
             15 POP_JUMP_IF_FALSE       31

  5          18 LOAD_CONST               1 (<code object <lambda> at 0x101dbb530, file "<ipython-input-10-32b41e5f6f2b>", line 5>)
             21 MAKE_FUNCTION            0
             24 POP_TOP             
             25 JUMP_ABSOLUTE           31
             28 JUMP_ABSOLUTE           34
        >>   31 JUMP_FORWARD             0 (to 34)
        >>   34 LOAD_CONST               0 (None)
             37 RETURN_VALUE  

这有14条指示。

我在我的系统上使用默认的IPython做了这个,目前是2.7.5,但是您可以使用这种技术来配置您正在运行的任何版本的Python所需的任何内容。

答案 1 :(得分:3)

让我们检查字节码并看看!

>>> def f():
...   if foo == True and bar == False and baz == True:
...     pass
...
>>> def g():
...     if foo == True:
...         if bar == False:
...             if baz == True:
...                 pass
...
>>> dis.dis(f)
  2           0 LOAD_GLOBAL              0 (foo)
              3 LOAD_GLOBAL              1 (True)
              6 COMPARE_OP               2 (==)
              9 POP_JUMP_IF_FALSE       39
             12 LOAD_GLOBAL              2 (bar)
             15 LOAD_GLOBAL              3 (False)
             18 COMPARE_OP               2 (==)
             21 POP_JUMP_IF_FALSE       39
             24 LOAD_GLOBAL              4 (baz)
             27 LOAD_GLOBAL              1 (True)
             30 COMPARE_OP               2 (==)
             33 POP_JUMP_IF_FALSE       39

  3          36 JUMP_FORWARD             0 (to 39)
        >>   39 LOAD_CONST               0 (None)
             42 RETURN_VALUE
>>> dis.dis(g)
  2           0 LOAD_GLOBAL              0 (foo)
              3 LOAD_GLOBAL              1 (True)
              6 COMPARE_OP               2 (==)
              9 POP_JUMP_IF_FALSE       45

  3          12 LOAD_GLOBAL              2 (bar)
             15 LOAD_GLOBAL              3 (False)
             18 COMPARE_OP               2 (==)
             21 POP_JUMP_IF_FALSE       45

  4          24 LOAD_GLOBAL              4 (baz)
             27 LOAD_GLOBAL              1 (True)
             30 COMPARE_OP               2 (==)
             33 POP_JUMP_IF_FALSE       42

  5          36 JUMP_ABSOLUTE           42
             39 JUMP_ABSOLUTE           45
        >>   42 JUMP_FORWARD             0 (to 45)
        >>   45 LOAD_CONST               0 (None)
             48 RETURN_VALUE

几乎相同。实际的逻辑部分是完全相同的操作码序列。看起来第二个版本的跳转目标效率略低,因此g的运行速度可能会稍慢,但这可能会在Python版本之间发生变化,而且几乎总是无关紧要。