uh *_*per 11 python performance python-2.7 python-3.4
这个问题和我的回答让我想到了Python 2.7和Python 3.4之间的这种特殊区别.以简单的示例代码为例:
import timeit
import dis
c = 1000000
r = range(c)
def slow():
for pos in range(c):
r[pos:pos+3]
dis.dis(slow)
time = timeit.Timer(lambda: slow()).timeit(number=1)
print('%3.3f' % time)
Run Code Online (Sandbox Code Playgroud)
在Python 2.7中,我始终如一地获得0.165~Python 3.4 0.554~.反汇编之间唯一重要的区别是Python 2.7发出SLICE+3字节代码,而Python 3.4 BUILD_SLICE随后发出BINARY_SUBSCR.请注意,我已经从其他问题中消除了潜在减速的候选者,即字符串和xrangePython 3.4中不存在的事实(range无论如何,它应该与后者的类相似).
使用itertools' islice两者之间几乎完全相同的时间,所以我高度怀疑这是切片,这是造成差异的原因.
为什么会发生这种情况,是否存在指向行为变化的权威来源的链接?
编辑:为了回答答案,我已经将range对象包裹起来list,这确实给出了明显的加速.然而,当我增加迭代次数时,timeit我注意到时序差异变得越来越大.作为一个完整性检查,我替换切片与None看看会发生什么.
500次迭代timeit.
c = 1000000
r = list(range(c))
def slow():
for pos in r:
None
Run Code Online (Sandbox Code Playgroud)
收益率10.688和收益率9.915.分别用for pos in islice(r, 0, c, 3)yield 7.626和for替换for循环6.270.分别替换None为r[pos]屈服20~和28~.r[pos:pos+3]收益率67.531和收益率106.784.
如您所见,时间差异很大.同样,我仍然相信这个问题与此没有直接关系range.
use*_*ica 10
在Python 2.7上,您将遍历列表并切片列表.在Python 3.4上,你将迭代range并切片arange.
当我在两个Python版本上运行带有列表的测试时:
from __future__ import print_function
import timeit
print(timeit.timeit('x[5:8]', setup='x = list(range(10))'))
Run Code Online (Sandbox Code Playgroud)
我得到关于Python 2.70.243554830551秒和0.29082867689430714秒关于Python 3.4,一个更小的差异.
消除range对象后看到的性能差异要小得多.它主要来自两个因素:在Python 3上添加速度稍慢,而Python 3需要__getitem__使用切片对象进行切片,而Python 2则需要__getslice__.
我无法复制你看到的时间差异r[pos]; 你可能在这个测试中遇到了一些混淆因素.