假设我们有两段代码:
if foo == True and bar == False and baz == True:
do something
和
if foo == True:
if bar == False:
if baz == True:
do something
哪个更快?
答案 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版本之间发生变化,而且几乎总是无关紧要。