python的控制流语句的性能

我正在阅读关于
loops的Python维基,它说

List comprehensions were added to Python in version 2.0 as well. They provide a syntactically more compact and more efficient way of writing the above for loop:

但是,我发现当我测试这个时,我会得到一些意想不到的结果.

In [22]: def while_loop(n):
    ...:     i = 0
    ...:     while i < n:
    ...:         i+=1
    ...:

In [23]: def while_loop_2(n):
    ...:     while n > 0:
    ...:         n-=1
    ...:

In [24]: def for_loop(n):
    ...:     for _ in range(n):
    ...:         pass
    ...:

In [30]: %timeit(for_loop(1000000))
10 loops, best of 3: 23.9 ms per loop

In [31]: %timeit(while_loop(1000000))
10 loops, best of 3: 37.1 ms per loop

In [32]: %timeit(while_loop_2(1000000))
10 loops, best of 3: 38 ms per loop

In [33]: %timeit([1 for _ in range(1000000)])
10 loops, best of 3: 43.2 ms per loop

这引出了一些问题:

>为什么for循环比列表理解快得多? (它似乎快了近两倍)
>为什么while_loop_2比while_loop慢?为什么递增与递减计数器的差异会产生速度上的差异?我的天真使我相信更少的代码行=更快 – 显然情况并非如此

编辑:
这是在Python 2.7中完成的.在3.6中,while_loop_2实际上比while_loop快.所以新问题:

> Python 2.7和3.x之间的while循环有什么区别?

最佳答案 作为序言,你应该意识到你的“比较”应该被孤立地分析(而不是相互比较),因为

> for循环是一个固定的迭代器,它的身体内部什么都不做
> while循环在它们的身体中执行递减/递增,并且
>列表理解不仅仅是一个for循环,并且据说,我会回答问题#1.

#1,因为for循环迭代.列表推导迭代,并在内存中创建一个列表.当然,这有助于节省总时间.仅此一点就足以说服你,但如果不是,请查看反汇编的字节代码,看看每个人在做什么.您可以使用dis模块执行此操作.我实际上用dis来回答你的第三个问题.

#2,至于这个,我无法在python3.6上重现.

%%timeit
i = 0; n = 100000
while i < n: i += 1

11.5 ms ± 65.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit
n = 100000
while  n > 0: n -= 1

10.8 ms ± 380 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

通常,基于递减的循环应该更快一些,因为与0(n> 0)的比较通常比与非零值(i

import dis

python3.6

06003

python2.7

06004

请注意,生成的字节码存在巨大差异.不同之处在于.

点赞