为什么会出现在Python3没有的xrange功能?(Why is there no xrange

2019-07-20 08:15发布

最近,我开始使用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

这是为什么? 我的意思是,为什么x范围已移除? 它是这样一个学习的好工具。 对于初学者来说,就像我自己一样,大家都在某一点。 为什么要删除它? 可有人点我到正确的PEP,我找不到它。

干杯。

Answer 1:

一些性能测量,使用timeit ,而不是试图用做手工time

首先,苹果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 。 和运算的xrange功能无关,用它做。 (并不奇怪,因为一次性调用__iter__插槽是不可能中千万调用在循环无论发生什么事,但有人把它作为一种可能性是可见的。)

但它慢了30%。 在OP是怎么2X一样慢? 好吧,如果我重复使用32位的Python相同的测试,我得到1.58 3.12对比。 所以我的猜测是,这又是一个在哪里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的时间超过两倍的时间比整个迭代多。

至于“消耗比Python 2.6+更多的资源”,从我的测试中,它看起来像一个3.x的range恰好是大小为2.x的相同xrange -and,即使有10倍那么大,建设不必要的名单仍有约10000000x比什么范围内可以反复做可能有问题的。

并且怎么样一个明确for循环,而不是内部的C循环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被删除,不管人多少次告诉你同样的事情,但我再重申一遍:这是不会被删除:它改名为range ,并在2.x range是什么除去。

下面是一些证据,证明3.3 range对象是2.X的直系后裔xrange对象(而不是在2.x range功能):源到3.3 range和2.7 xrange 。 你甚至可以看到改变历史 (挂,我相信,替换字符串“x范围”,在文件的任何地方的最后一个实例的变化)。

那么,为什么会慢?

那么,对于一个,他们已经增加了许多新功能。 另一个原因是,他们做了各种变化的各地有轻微的副作用的地方(特别是内迭代)。 而且有自己被大量的工作极大地优化各种重要的情况下,即使它有时稍pessimizes不太重要的案件。 加入这一切了,我并不感到惊讶,遍历一个range尽可能快地现在是有点慢。 这是那没有人会在意得关注那些不太重要的案件之一。 没有人可能曾经有一个真实的使用情况下这种性能差异在他们的代码中的热点。



Answer 2:

Python3的范围 Python2的x范围。 有没有必要环绕它的国际热核实验堆。 要获得Python3的实际列表,你需要使用list(range(...))

如果你想要的东西,与Python2和Python3工作,试试这个

try:
    xrange
except NameError:
    xrange = range


Answer 3:

Python 3中的range类型的作品就像Python的2的xrange 。 我不知道为什么你看到放缓,因为你返回的迭代器xrange功能是完全如果你遍历你会得到什么range直接。

我无法重现我的系统上放缓。 以下是我测试:

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

Python 3中,具有range是一点点更快:

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

我最近了解到的Python 3的range类型有其他一些简洁的功能,如切片支持: range(10,100,2)[5:25:5]range(15, 60, 10)



Answer 4:

修复你的python2代码的方法是:

import sys

if sys.version_info >= (3, 0):
    def xrange(*args, **kwargs):
        return iter(range(*args, **kwargs))


Answer 5:

在Python 2 x范围是发电机和而范围仅仅是一个函数实现迭代器。 在Python3我不知道为什么被丢弃掉的xrange。



Answer 6:

排版:〜$蟒的Python 2.7.6(默认情况下,2015年6月22日,17点58分十三秒)[4.8.2 GCC] linux2的上

>>> import timeit
>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)

5.656799077987671

>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)

5.579368829727173

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

21.54827117919922

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

22.014557123184204

与timeit编号= 1 PARAM:

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=1)

0.2245171070098877

>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=1)

0.10750913619995117

排版:〜$ python3的Python 3.4.3(默认,二○一五年十月一十四日,20点28分29秒)[GCC 4.8.4]在Linux

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

9.113872020003328

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

9.07014398300089

随着timeit数= 1,2,3,4 PARAM工作快速而线性方式:

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=1)

0.09329321900440846

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=2)

0.18501482300052885

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=3)

0.2703447980020428

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=4)

0.36209142999723554

如此看来,如果我们用像timeit.timeit 1个运转循环周期(“[x对于如果范围(X 1000000)X%4]”,数= 1)(正如我们在真正的代码实际上使用)python3足够快的工作,但在反复循环蟒2 x范围()获得在从蟒3对范围的速度()。



文章来源: Why is there no xrange function in Python3?