36

为什么if Trueif 1Python 慢?不if True应该比 快if 1吗?

我正在尝试学习该timeit模块。从基础开始,我尝试了这些:

>>> def test1():
...     if True:
...         return 1
...     else:
...         return 0

>>> print timeit("test1()", setup = "from __main__ import test1")
0.193144083023


>>> def test2():
...     if 1:
...         return 1
...     else:
...         return 0

>>> print timeit("test2()", setup = "from __main__ import test2")
0.162086009979


>>> def test3():
...     if True:
...             return True
...     else:
...             return False

>>> print timeit("test3()", setup = "from __main__ import test3")
0.214574098587

>>> def test4():
...     if 1:
...             return True
...     else:
...             return False

>>> print timeit("test4()", setup = "from __main__ import test4")
0.160849094391

我对这些事情感到困惑:

  1. 根据 Sylvain Defresne 先生在这个问题中的回答,一切都被隐式转换为bool第一个然后检查。那么为什么if True比 慢if 1
  2. 为什么test3test1只有return值不同时慢?
  3. 像问题 2,但为什么比test4一点?test2

注意:我跑了timeit3 次,取了结果的平均值,然后把时间和代码一起贴在这里。

这个问题与如何进行微基准测试无关(我在这个例子中做了,但我也明白它太基础了),但为什么检查“真”变量比常数慢。

4

2 回答 2

41

True并且False不是Python 2中的关键字。

它们必须在运行时解析。这在Python 3中已更改

在 Python 3 上进行相同的测试:

>>> timeit.timeit('test1()',setup="from __main__ import test1", number=10000000)
2.806439919999889
>>> timeit.timeit('test2()',setup="from __main__ import test2", number=10000000)
2.801301520000038
>>> timeit.timeit('test3()',setup="from __main__ import test3", number=10000000)
2.7952816800000164
>>> timeit.timeit('test4()',setup="from __main__ import test4", number=10000000)
2.7862537199999906

时间误差在 1% 以内,这是可以接受的。

于 2013-08-08T10:51:29.963 回答
20

字节码反汇编使差异显而易见。

>>> dis.dis(test1)
  2           0 LOAD_GLOBAL              0 (True)
              3 JUMP_IF_FALSE            5 (to 11)
              6 POP_TOP             

  3           7 LOAD_CONST               1 (1)
             10 RETURN_VALUE        
        >>   11 POP_TOP             

  5          12 LOAD_CONST               2 (0)
             15 RETURN_VALUE        
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE        

正如 Kabie 提到的,True并且False是 Python 2 中的全局变量。很多东西都在访问它们。

>>> dis.dis(test2)
  3           0 LOAD_CONST               1 (1)
              3 RETURN_VALUE        

Python 编译器能够识别1出一个不断“真实”的表达式,并优化掉多余的条件!

>>> dis.dis(test3)
  2           0 LOAD_GLOBAL              0 (True)
              3 JUMP_IF_FALSE            5 (to 11)
              6 POP_TOP             

  3           7 LOAD_GLOBAL              0 (True)
             10 RETURN_VALUE        
        >>   11 POP_TOP             

  5          12 LOAD_GLOBAL              1 (False)
             15 RETURN_VALUE        
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE        

差不多一样test1,多了一个LOAD_GLOBAL

>>> dis.dis(test4)
  3           0 LOAD_GLOBAL              0 (True)
              3 RETURN_VALUE        

test2。但LOAD_GLOBALLOAD_CONST.

于 2013-08-08T11:01:03.493 回答