最近我开始使用 Python3,它没有xrange什么缺点。
xrange
简单示例:
py from time import time as t def count(): st = t() [x for x in xrange(10000000) if x%4 == 0] et = t() print et-st count()
```py from time import time as t
def xrange(x):
return iter(range(x))
def count(): st = t() [x for x in xrange(10000000) if x%4 == 0] et = t() print (et-st) count() ```
结果分别为:
1.53888392448
3.215819835662842
为什么会这样?我的意思是,为什么xrange它被删除了?它是一个很好的学习工具。对于初学者来说,就像我一样,我们都曾经有过这样的经历。为什么要删除它?有人能告诉我正确的 PEP 在哪里吗,我找不到。
一些性能测量,使用timeit而不是尝试手动完成time。
timeit
time
首先,Apple 2.7.2 64位:
In [37]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0) 1 loops, best of 3: 1.05 s per loop
现在,python.org 3.3.0 64位:
In [83]: %timeit collections.deque((x for x in range(10000000) if x%4 == 0), maxlen=0) 1 loops, best of 3: 1.32 s per loop In [84]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0) 1 loops, best of 3: 1.31 s per loop In [85]: %timeit collections.deque((x for x in iter(range(10000000)) if x%4 == 0), maxlen=0) 1 loops, best of 3: 1.33 s per loop
显然, 3.xrange确实比 2.x 慢一点xrange。而 OP 的xrange功能与此无关。(这并不奇怪,因为__iter__在循环中发生的 10000000 次调用中,对插槽的一次性调用不太可能可见,但有人提出这是有可能的。)
range
__iter__
但它只慢了 30%。楼主的速度怎么会慢 2 倍呢?好吧,如果我用 32 位 Python 重复同样的测试,我得到的结果为 1.58,而 3.12 则为 1.58。所以我猜这又是 3.x 针对 64 位性能进行了优化,但会损害 32 位性能的又一个案例。
但这真的很重要吗?再次使用 3.3.0 64 位检查一下:
In [86]: %timeit [x for x in range(10000000) if x%4 == 0] 1 loops, best of 3: 3.65 s per loop
因此,构建所list花的时间是整个迭代的两倍多。
list
至于“比 Python 2.6+ 消耗更多的资源”,从我的测试来看,3.x 的range大小与 2.x 完全相同xrange- 并且,即使它大 10 倍,构建不必要的列表仍然比范围迭代可能做的任何事情都要麻烦 10000000 倍。
for那么如果使用显式循环来代替里面的 C 循环会怎么样呢deque?
for
deque
In [87]: def consume(x): ....: for i in x: ....: pass In [88]: %timeit consume(x for x in range(10000000) if x%4 == 0) 1 loops, best of 3: 1.85 s per loop
因此,在for声明中浪费的时间几乎与在实际迭代工作中浪费的时间一样多range。
如果您担心优化范围对象的迭代,那么您可能找错了地方。
同时,xrange无论别人多少次告诉你同样的事情,你还是会问为什么被删除,但我会再重复一遍:它并没有被删除:它被重命名为,并且被删除的是range2.x。range
这里有一些证据表明 3.3对象是 2.x对象(而不是 2.x函数)range的直接后代: 3.3和2.7的来源。您甚至可以看到更改历史记录(我相信链接到替换文件中任何位置的字符串“xrange”的最后一个实例的更改)。xrange``rangerangexrange
xrange``range
那么,为什么它变慢了呢?
嗯,首先,他们添加了很多新功能。其次,他们在各处(尤其是在迭代内部)做了各种各样的更改,这些更改的副作用很小。而且他们做了很多工作来显著优化各种重要情况,即使有时它稍微低估了不太重要的情况。把所有这些加起来,我并不惊讶尽可能range快的迭代现在变得有点慢了。这是那些不太重要的情况之一,没有人会足够关心并关注它。没有人可能在实际用例中遇到这种性能差异是他们代码中的热点。