最近我开始使用Python3,它缺少xrange
带来的伤害。
简单的例子:
从时间导入时间as t def count():st = t() x for x in xrange(10000000) if x%4 == 0 et = t() print et-st count()
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吗,我找不到了。
发布于 2013-02-22 08:03:11
一些性能测量,使用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.x的range
确实比2.x的xrange
慢一点。OP的xrange
函数与此无关。(这并不奇怪,因为对__iter__
插槽的一次性调用不太可能在对循环中发生的任何事情的10000000个调用中可见,但有人提出了这种可能性。)
但它只慢了30%。操作怎么会变得慢2倍呢?好吧,如果我用32位的Python重复同样的测试,我得到的结果是1.58比3.12。所以我的猜测是,这是3.x以损害32位的方式针对64位性能进行优化的另一种情况。
但这真的很重要吗?看看这个,再次使用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
所需的时间是整个迭代的两倍多。
至于“比Python 2.6+消耗更多的资源”,从我的测试来看,3.x的range
看起来和2.x的xrange
-and的大小完全一样,即使它是10倍的大小,构建不必要的列表仍然是一个比范围迭代可能做的任何事情都多1000000倍的问题。
在deque
中使用显式的for
循环而不是C循环又如何呢
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
的实际工作中浪费的时间一样多。
如果您担心优化range对象的迭代,那么您可能找错了地方。
与此同时,你一直在问为什么xrange
被删除了,不管人们多少次告诉你同样的事情,但我再重复一次:它没有被删除:它被重命名为range
,而2.x的range
才是被删除的。
这里有一些证据证明3.3 range
对象是2.x xrange
对象(而不是2.x range
函数)的直接后代:3.3 range
和2.7 xrange
的源。您甚至可以在文件中的任何位置看到change history (链接到替换了字符串"xrange“的最后一个实例的更改)。
那么,为什么它变慢了呢?
首先,他们增加了很多新功能。另一方面,他们在所有地方都做了各种各样的更改(特别是在迭代内部),这些更改都有轻微的副作用。而且已经有很多工作来戏剧性地优化各种重要的情况,即使它有时会使不太重要的情况稍微悲观一些。综上所述,我并不奇怪现在尽可能快地迭代range
的速度变慢了一点。这是那些不太重要的案例之一,没有人会足够在意来关注它。在现实生活中,这种性能差异是代码中的热点,没有人可能会有这样的用例。
发布于 2013-02-22 09:09:29
Python3的范围是Python2的xrange。没有必要用iter把它包裹起来。要获得Python3中的实际列表,需要使用list(range(...))
如果你想要与Python2和Python3一起工作的东西,试试这个
try:
xrange
except NameError:
xrange = range
发布于 2013-02-22 07:42:08
Python3的range
类型的工作方式与Python2的xrange
类似。我不知道为什么您会看到速度变慢,因为如果您直接在range
上迭代,xrange
函数返回的迭代器就是您所得到的。
我不能在我的系统上重现减速。下面是我测试的方法:
Python 2,带xrange
Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)
18.631936646865853
使用range
的Python3要快一点:
Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)
17.31399508687869
我最近了解到Python3的range
类型还有其他一些巧妙的特性,比如对切片的支持:range(10,100,2)[5:25:5]
is range(20, 60, 10)
!
https://stackoverflow.com/questions/15014310
复制相似问题