这是an answer I gave a few days back的后续问题。 编辑:似乎这个问题的OP已经使用我发布给他的代码问the same question,但我没有意识到这一点。道歉。提供的答案是不同的!为什么早退比其他退?
基本上我观察到:
>>> def without_else(param=False):
... if param:
... return 1
... return 0
>>> def with_else(param=False):
... if param:
... return 1
... else:
... return 0
>>> from timeit import Timer as T
>>> T(lambda : without_else()).repeat()
[0.3011460304260254, 0.2866089344024658, 0.2871549129486084]
>>> T(lambda : with_else()).repeat()
[0.27536892890930176, 0.2693932056427002, 0.27011704444885254]
>>> T(lambda : without_else(True)).repeat()
[0.3383951187133789, 0.32756996154785156, 0.3279120922088623]
>>> T(lambda : with_else(True)).repeat()
[0.3305950164794922, 0.32186388969421387, 0.3209099769592285]
...或者换句话说:具有else
子句是更快不管被触发或不if
条件。
我认为它必须处理两个不同的字节码,但是有人能够确认/详细解释吗?
编辑:似乎不是每个人都能够重现我的时间,所以我认为这可能是有用的给我的系统一些信息。我正在运行安装了默认python的Ubuntu 11.10 64位。 python
生成以下版本信息:
Python 2.7.2+ (default, Oct 4 2011, 20:06:09)
[GCC 4.6.1] on linux2
以下是拆卸在Python 2.7的结果:
>>> dis.dis(without_else)
2 0 LOAD_FAST 0 (param)
3 POP_JUMP_IF_FALSE 10
3 6 LOAD_CONST 1 (1)
9 RETURN_VALUE
4 >> 10 LOAD_CONST 2 (0)
13 RETURN_VALUE
>>> dis.dis(with_else)
2 0 LOAD_FAST 0 (param)
3 POP_JUMP_IF_FALSE 10
3 6 LOAD_CONST 1 (1)
9 RETURN_VALUE
5 >> 10 LOAD_CONST 2 (0)
13 RETURN_VALUE
14 LOAD_CONST 0 (None)
17 RETURN_VALUE
有一个相同的问题,所以我现在找不到。他们检查了生成的字节码,还有一个额外的步骤。观察到的差异非常依赖于测试者(机器,SO ..),有时只发现非常小的差异。 – joaquin
在3.x上,它们都产生了**相同的**字节码,保存了一些无法访问的代码('LOAD_CONST(None); RETURN_VALUE' - 但如前所述,它从来没有达到)在'with_else'结尾。我非常怀疑死代码使得函数更快。有人可以在2.7上提供“dis”吗? – delnan
我无法重现这一点。带有'else'和'False'的函数是其中最慢的(152ns)。第二快的是没有“其他”(143ns)的“True”,另外两个基本相同(137ns和138ns)。我没有使用默认参数,并使用iPython中的'%timeit'来测量它。 – rplnt