【问题标题】:Why is if True slower than if 1?为什么 if True 比 if 1 慢?
【发布时间】:2013-08-10 01:03:49
【问题描述】:

为什么在 Python 中 if Trueif 1 慢? 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 先生在this question 中的回复,所有内容都先隐式转换为bool,然后再进行检查。那么为什么if Trueif 1 慢?
  2. 为什么 test3test1 慢,即使只有 return 值不同?
  3. 类似于问题 2,但为什么 test4test2 稍微

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

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

【问题讨论】:

  • 我认为你的测试太小了。而且平均三轮是不够的:p
  • 我明白 :) 即使是测试用例也太基础了,无法思考。但是,我们需要从正确的地方开始 :)
  • @JarrodRoberson 感谢您的链接:-) 但是,我的问题与通用微型基准测试无关。这是关于为什么使用关键字检查布尔值比检查常量慢。
  • True 的输入时间是数字 1 的 4 倍

标签: python performance if-statement boolean timeit


【解决方案1】:

TrueFalse 不是 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%以内,可以接受。

【讨论】:

  • 试试True,False=False,True
【解决方案2】:

字节码反汇编效果明显。

>>> 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 提到的,TrueFalse 在 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 贵一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-31
    • 1970-01-01
    • 2012-07-06
    • 1970-01-01
    • 2021-07-11
    • 2011-10-06
    • 2020-08-15
    • 1970-01-01
    相关资源
    最近更新 更多