Python 使用if语句的While循环比While循环快

Python 使用if语句的While循环比While循环快,python,performance,if-statement,python-3.x,while-loop,Python,Performance,If Statement,Python 3.x,While Loop,我正在测试循环中if语句的速度及其对速度的影响。我发现,if语句始终提高了性能。我的代码: import time t = time.time start = t() x = 0 while x < 10000000: x += 1 time1 = t() x = 0 while x < 10000000: x += 1 if True: pass time2 = t() print(start) print(time1 - start)

我正在测试循环中if语句的速度及其对速度的影响。我发现,if语句始终提高了性能。我的代码:

import time
t = time.time

start = t()
x = 0
while x < 10000000:
    x += 1
time1 = t()
x = 0
while x < 10000000:
    x += 1
    if True:
        pass
time2 = t()

print(start)
print(time1 - start) # Time for simple while-loop
print(time2 - time1) # Time for while+if

这完全违反直觉。while-if循环的工作速度比标准while循环稍快。几乎每次我运行它时都会发生这种情况;也许每20次中就有1次需要更长的时间。有人知道为什么吗?

我猜编译器会删除if-True块,因为它是常量

当我跑步时,我从你那里得到的结果大多是相反的。我可能只是执行环境的随机影响

1355519587.2 0.832797050476 1.04382395744

1355519590.03 0.863899946213 1.09347200394

1355519593.72 0.831655025482 1.05389809608

1355519599.71 0.831452131271 1.41783499718

1355519602.99 0.815280914307 1.05724310875

1355519605.72 0.826404094696 1.05700492859

1355519608.94 0.827296972275
1.07807898521

dis显示if语句的while循环有更多步骤

In [4]: dis.dis(t2)
  2           0 LOAD_CONST               1 (0)
              3 STORE_FAST               0 (x)

  3           6 SETUP_LOOP              26 (to 35)
        >>    9 LOAD_FAST                0 (x)
             12 LOAD_CONST               2 (10000000)
             15 COMPARE_OP               0 (<)
             18 POP_JUMP_IF_FALSE       34

  4          21 LOAD_FAST                0 (x)
             24 LOAD_CONST               3 (1)
             27 INPLACE_ADD
             28 STORE_FAST               0 (x)
             31 JUMP_ABSOLUTE            9
        >>   34 POP_BLOCK
        >>   35 LOAD_CONST               0 (None)
             38 RETURN_VALUE

In [5]: dis.dis(t1)
  2           0 LOAD_CONST               1 (0)
              3 STORE_FAST               0 (x)

  3           6 SETUP_LOOP              35 (to 44)
        >>    9 LOAD_FAST                0 (x)
             12 LOAD_CONST               2 (10000000)
             15 COMPARE_OP               0 (<)
             18 POP_JUMP_IF_FALSE       43

  4          21 LOAD_FAST                0 (x)
             24 LOAD_CONST               3 (1)
             27 INPLACE_ADD
             28 STORE_FAST               0 (x)

  5          31 LOAD_GLOBAL              0 (True)
             34 POP_JUMP_IF_FALSE        9

  6          37 JUMP_ABSOLUTE            9
             40 JUMP_ABSOLUTE            9
        >>   43 POP_BLOCK
        >>   44 LOAD_CONST               0 (None)
             47 RETURN_VALUE
[4]中的
:dis.dis(t2)
2 0负载常数1(0)
3存储单元快速0(x)
3 6设置回路26(至35)
>>9快速加载0(x)
12负载常数2(10000000)
15比较操作0(>34个弹出块
>>35负载常数0(无)
38返回值
In[5]:dis.dis(t1)
2 0负载常数1(0)
3存储单元快速0(x)
3 6设置回路35(至44)
>>9快速加载0(x)
12负载常数2(10000000)
15比较操作0(>43弹出块
>>44负载常数0(无)
47返回值

如果将
x=0
移出两个计时块会发生什么?我打赌您看到的是解释器必须为第一个块分配
x
,而不是第二个块。这里不一样,tho';我有类似的计时:
$python t.py 1355519439.65 1.92616391182 2.650105595322
;在python 2.7.3上运行的结果是相同的吗如果您先运行if循环,然后运行没有if循环的循环?对我来说,第一个循环总是更快。我得到了您在2.7中所期望的结果,以及在3.2中所得到的奇怪结果。第二个版本(在Python 3.2.3中)的运行时间也一直比预期的要长。请记住,
time.time()
不是分析程序的正确方法(因为其他任务可能会影响结果)。使用
timeit.timeit()
相反。哪个引擎?没有即时编译器或任何东西。至少在CPython中没有。事实上,根本没有编译器,我们这里讨论的是Python。同意。我的结果是:1355519852.98、0.830796003342、1.11595201492和Python 2.7。1@TimPietzcker,它是2.7.1。Python会编译,但会转换为字节码。您不能执行raw text在大多数操作环境中使用。@delnan:你能给出一个例子或一些文档的链接,说明编译器可以做什么样的优化吗?显然,它不能删除空的
if
语句。@TimPietzcker我认为这没有文档记录,因为它是一个实现细节,很少有什么关系我看到的Optimizer在中。当然,还有来源:(有很多评论详细说明了所执行的优化)。请参阅第446行,了解根据常量进行的跳转优化。感谢您发布这篇文章,我以前不知道dis模块。但是,while-if循环运行得更快,即使在非常低的级别,它也需要更多的步骤,这一点仍然令人困惑。
In [4]: dis.dis(t2)
  2           0 LOAD_CONST               1 (0)
              3 STORE_FAST               0 (x)

  3           6 SETUP_LOOP              26 (to 35)
        >>    9 LOAD_FAST                0 (x)
             12 LOAD_CONST               2 (10000000)
             15 COMPARE_OP               0 (<)
             18 POP_JUMP_IF_FALSE       34

  4          21 LOAD_FAST                0 (x)
             24 LOAD_CONST               3 (1)
             27 INPLACE_ADD
             28 STORE_FAST               0 (x)
             31 JUMP_ABSOLUTE            9
        >>   34 POP_BLOCK
        >>   35 LOAD_CONST               0 (None)
             38 RETURN_VALUE

In [5]: dis.dis(t1)
  2           0 LOAD_CONST               1 (0)
              3 STORE_FAST               0 (x)

  3           6 SETUP_LOOP              35 (to 44)
        >>    9 LOAD_FAST                0 (x)
             12 LOAD_CONST               2 (10000000)
             15 COMPARE_OP               0 (<)
             18 POP_JUMP_IF_FALSE       43

  4          21 LOAD_FAST                0 (x)
             24 LOAD_CONST               3 (1)
             27 INPLACE_ADD
             28 STORE_FAST               0 (x)

  5          31 LOAD_GLOBAL              0 (True)
             34 POP_JUMP_IF_FALSE        9

  6          37 JUMP_ABSOLUTE            9
             40 JUMP_ABSOLUTE            9
        >>   43 POP_BLOCK
        >>   44 LOAD_CONST               0 (None)
             47 RETURN_VALUE