最近我开始使用Python3,它缺乏xrange的伤害 .
简单的例子:
1) Python2:
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()
2) Python3:
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) 1.53888392448 2) 3.215819835662842
这是为什么?我的意思是,为什么xrange被删除了?这是一个很好的学习工具 . 对于初学者来说,就像我一样,就像我们所有人一样 . 为什么删除它?有人能指出我正确的PEP,我找不到它 .
干杯 .
6 回答
修复python2代码的一种方法是:
一些性能测量,使用
timeit
而不是尝试使用time
手动执行 .首先,Apple 2.7.2 64位:
现在,python.org 3.3.0 64位:
显然,3.x
range
确实比2.xxrange
慢一点 . OP的xrange
功能与它无关 . (这并不奇怪,因为在循环中发生的10000000次调用中,一次性调用__iter__
插槽的可能性不大,但是有人提出这种情况 . )但它只慢了30% . OP如何获得2倍的速度?好吧,如果我用32位Python重复相同的测试,我得到1.58和3.12 . 所以我的猜测是,这是另一种情况,其中3.x已经针对损害32位的方式针对64位性能进行了优化 .
但它真的重要吗?再次检查这一点,再次使用3.3.0 64位:
因此,构建
list
的时间比整个迭代长两倍多 .至于"consumes much more resources than Python 2.6+",从我的测试来看,它看起来像3.x
range
与2.xxrange
完全相同 - 即使它是10倍大,构建不必要的列表仍然是大约10000000倍问题比范围迭代可能做的任何事情都要多 .那个显式的
for
循环而不是deque
中的C循环呢?因此,在
for
语句中浪费的时间与迭代range
的实际工作几乎一样多 .如果您担心优化范围对象的迭代,那么您可能正在查找错误的位置 .
同时,你不断问为什么
xrange
被删除,无论人们多少次告诉你同样的事情,但我会再次重复:它没有删除:它被重命名为range
,而2.xrange
是什么的除去 .这里有一些证据证明3.3
range
对象是2.xxrange
对象的直接后代(而不是2.xrange
函数):3.3 range和2.7 xrange的源 . 您甚至可以看到change history(链接到,我相信,更改了替换文件中任何位置的字符串"xrange"的最后一个实例) .那么,为什么它会变慢?
嗯,对于其中一个,他们已经做了各种各样的变化(特别是在迭代中),这些变化有轻微的副作用 . 并且'd been a lot of work to dramatically optimize various important cases, even if it sometimes slightly pessimizes less important cases. Add this all up, and I'毫不奇怪,尽可能快地迭代
range
现在有点慢 . 这是一个不那么重要的案例,没有人会关注到足够关注 . 任何人都不可能有一个真实的用例,其中这种性能差异是他们代码中的热点 .Python 3的
range
类型就像Python 2的xrange
一样 . 我看到了一个减速,因为xrange
函数返回的迭代器正是你直接迭代range
所得到的 .我无法重现系统的减速 . 这是我测试的方式:
Python 2,带
xrange
:Python 3,
range
更快一点:我最近了解到Python 3的
range
类型还有一些其他简洁的功能,比如支持切片:range(10,100,2)[5:25:5]
是range(15, 60, 10)
!comp:~$ python Python 2.7.6(默认,2015年6月22日,17:58:13)linux2上的[GCC 4.8.2]
5.656799077987671
5.579368829727173
21.54827117919922
22.014557123184204
With timeit number=1 param:
0.2245171070098877
0.10750913619995117
comp:~$ python3 Python 3.4.3(默认,2015年10月14日,20:28:29)[GCC 4.8.4]在linux上
9.113872020003328
9.07014398300089
With timeit number=1,2,3,4 param works quick and in linear way:
0.09329321900440846
0.18501482300052885
0.2703447980020428
0.36209142999723554
因此,如果我们测量1个正在运行的循环周期,例如timeit.timeit(“[x for x in range(1000000)if x%4]”,number = 1)(正如我们在实际代码中实际使用的那样),python3工作得足够快,但是在重复循环中,python 2 xrange()在python 3中对range()的速度获胜 .
Python3的范围是Python2 's xrange. There',无需围绕它进行包装 . 要在Python3中获取实际列表,您需要使用
list(range(...))
如果你想要一些适用于Python2和Python3的东西,试试这个
Python 2中的xrange是一个生成器并实现了迭代器,而range只是一个函数 . 在Python3中,我不知道为什么从xrange中删除了 .