为什么如果True比1慢?

thi*_*dam 29 python performance if-statement boolean timeit

为什么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
Run Code Online (Sandbox Code Playgroud)

我对这些事感到困惑:

  1. 根据Sylvain Defresne先生在这个问题中的回答,一切都被隐含地转换为bool第一个然后检查.那么为什么if Trueif 1
  2. 为什么test3速度慢,test1即使只有return值不同?
  3. 像问题2,但为什么比test4一点test2

注意:我跑timeit了三次并取结果的平均值,然后将这些时间与代码一起发布.

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

Kab*_*bie 32

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
Run Code Online (Sandbox Code Playgroud)

时间误差为1%,这是可以接受的.

  • 尝试'真,假=假,真' (4认同)

rkh*_*rov 18

字节拆卸使得差异明显.

>>> 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        
Run Code Online (Sandbox Code Playgroud)

正如Kabie所提到的,True并且False是Python 2中的全局变量.很多东西正在进行访问.

>>> dis.dis(test2)
  3           0 LOAD_CONST               1 (1)
              3 RETURN_VALUE        
Run Code Online (Sandbox Code Playgroud)

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        
Run Code Online (Sandbox Code Playgroud)

几乎一样test1,还有一个LOAD_GLOBAL.

>>> dis.dis(test4)
  3           0 LOAD_GLOBAL              0 (True)
              3 RETURN_VALUE        
Run Code Online (Sandbox Code Playgroud)

test2.但是LOAD_GLOBAL要比它贵一点LOAD_CONST.