Python 您是否应该总是喜欢xrange()而不是range()?

Python 您是否应该总是喜欢xrange()而不是range()?,python,range,xrange,Python,Range,Xrange,为什么或为什么不?xrange()效率更高,因为它一次只生成一个对象,而不是生成对象列表。而不是100个整数,以及它们的所有开销,以及将它们放入的列表,一次只需要一个整数。更快的生成,更好的内存使用,更高效的代码 除非我特别需要某个列表,否则我总是喜欢xrange()只有当你需要实际的列表时,你才应该喜欢range()而不是xrange()。例如,当您想要修改range()返回的列表时,或者当您想要对其进行切片时。对于迭代,甚至是普通的索引,xrange()可以很好地工作(通常效率更高)。对于非

为什么或为什么不?

xrange()
效率更高,因为它一次只生成一个对象,而不是生成对象列表。而不是100个整数,以及它们的所有开销,以及将它们放入的列表,一次只需要一个整数。更快的生成,更好的内存使用,更高效的代码


除非我特别需要某个列表,否则我总是喜欢
xrange()

只有当你需要实际的列表时,你才应该喜欢
range()
而不是
xrange()
。例如,当您想要修改
range()
返回的列表时,或者当您想要对其进行切片时。对于迭代,甚至是普通的索引,
xrange()
可以很好地工作(通常效率更高)。对于非常小的列表,
range()
xrange()
稍微快一点,但取决于您的硬件和各种其他细节,盈亏平衡可能是长度为1或2的结果;没什么好担心的。出于以下原因,首选
xrange()

使用range:

1) xrange将在较新的Python版本中消失。这为您提供了方便的未来兼容性


2) range将具有与xrange相关的效率。

对于性能,尤其是在大范围内迭代时,
xrange()
通常更好。但是,仍然有一些情况下您可能更喜欢
range()

  • 在Python3中,
    range()
    执行
    xrange()
    过去所做的操作,而
    xrange()
    不存在。如果要编写同时在Python2和Python3上运行的代码,则不能使用
    xrange()

  • range()
    在某些情况下实际上可以更快—例如,如果在同一序列上迭代多次
    xrange()
    每次都必须重构整数对象,但是
    range()
    将具有真实的整数对象。(但在记忆方面,它的表现总是更差)

  • xrange()
    不能在所有需要实际列表的情况下使用。例如,它不支持切片或任何列表方法

[编辑]有几篇文章提到了2to3工具将如何升级
range()
。作为记录,这里是在
range()
xrange()

如您所见,当在for循环或理解中使用时,或者在已经用list()包装的地方,range保持不变。

range()返回列表,xrange()返回xrange对象

xrange()速度更快,内存效率更高。但收益并不是很大

列表使用的额外内存当然不仅仅是浪费,列表还有更多的功能(切片、重复、插入等)。确切的差异可以在中找到。没有bonehard规则,需要什么就用什么


Python 3.0仍在开发中,但IIRC range()将与2.X版本的xrange()非常相似,可以使用list(range())生成列表。

好的,这里的每个人都对xrange与range的利弊持不同意见。它们基本上是正确的,xrange是一个迭代器,range充实并创建了一个实际的列表。对于大多数情况,您不会真正注意到两者之间的差异。(可以将贴图与range一起使用,但不能与xrange一起使用,但会占用更多内存。)


然而,我想你想听的是,首选的是xrange。由于Python3中的range是一个迭代器,因此代码转换工具2to3将正确地将xrange的所有用法转换为range,并将抛出一个错误或警告。如果您希望确保将来可以轻松地转换代码,那么您将仅使用xrange,并且在确定需要列表时使用list(xrange)。我在今年(2008年)芝加哥PyCon的CPython sprint比赛中了解到了这一点。

不,它们都有各自的用途:

迭代时使用
xrange()
,因为这样可以节省内存。说:

for x in xrange(1, one_zillion):
而不是:

for x in range(1, one_zillion):
另一方面,如果您确实想要一个数字列表,请使用
range()

multiples_of_seven = range(7,100,7)
print "Multiples of seven < 100: ", multiples_of_seven
乘以七的倍数=范围(7100,7)
打印“七的倍数<100:”,七的倍数

我想说的是,获得具有切片和索引功能的xrange对象并不难。我已经写了一些代码,工作得非常好,在计算(迭代)时与xrange一样快

来自未来进口部的

def读取范围(范围对象):
#返回xrange对象的开始、停止和步骤
开始=xrange\u对象[0]
如果len(xrange_对象)>1:
步骤=xrange\u对象[1]-xrange\u对象[0]
其他:
步骤=1
停止=xrange\u对象[-1]+步长
返回开始、停止、步骤
类别X范围(对象):
''创建一个类似xrange的对象,该对象支持切片和索引。
例:a=X范围(20)
a、 索引(10)
行得通
也是a[:5]
将返回另一个具有指定属性的Xrange对象
还允许从现有xrange对象进行转换
'''
定义初始化(自,*输入):
#允许输入xrange对象
如果len(输入)==1:
测试,=输入
如果类型(测试)=X范围:
self.xrange=测试
self.start、self.stop、self.step=读取范围(测试)
返回
#或者从开始、停止、步骤创建一个
self.start,self.step=0,无
如果len(输入)==1:
自停止,=输入
elif len(输入)==2:
自启动、自停止=输入
elif len(输入)==3:
self.start、self.stop、self.step=输入
其他:
提升值错误(输入)
self.xrange=xrange(self.start、self.stop、self.step)
定义(自我):
返回iter(self.xrange)
定义uuu获取项目uuuu(自我
multiples_of_seven = range(7,100,7)
print "Multiples of seven < 100: ", multiples_of_seven
from __future__ import division

def read_xrange(xrange_object):
    # returns the xrange object's start, stop, and step
    start = xrange_object[0]
    if len(xrange_object) > 1:
       step = xrange_object[1] - xrange_object[0]
    else:
        step = 1
    stop = xrange_object[-1] + step
    return start, stop, step

class Xrange(object):
    ''' creates an xrange-like object that supports slicing and indexing.
    ex: a = Xrange(20)
    a.index(10)
    will work

    Also a[:5]
    will return another Xrange object with the specified attributes

    Also allows for the conversion from an existing xrange object
    '''
    def __init__(self, *inputs):
        # allow inputs of xrange objects
        if len(inputs) == 1:
            test, = inputs
            if type(test) == xrange:
                self.xrange = test
                self.start, self.stop, self.step = read_xrange(test)
                return

        # or create one from start, stop, step
        self.start, self.step = 0, None
        if len(inputs) == 1:
            self.stop, = inputs
        elif len(inputs) == 2:
            self.start, self.stop = inputs
        elif len(inputs) == 3:
            self.start, self.stop, self.step = inputs
        else:
            raise ValueError(inputs)

        self.xrange = xrange(self.start, self.stop, self.step)

    def __iter__(self):
        return iter(self.xrange)

    def __getitem__(self, item):
        if type(item) is int:
            if item < 0:
                item += len(self)

            return self.xrange[item]

        if type(item) is slice:
            # get the indexes, and then convert to the number
            start, stop, step = item.start, item.stop, item.step
            start = start if start != None else 0 # convert start = None to start = 0
            if start < 0:
                start += start
            start = self[start]
            if start < 0: raise IndexError(item)
            step = (self.step if self.step != None else 1) * (step if step != None else 1)
            stop = stop if stop is not None else self.xrange[-1]
            if stop < 0:
                stop += stop

            stop = self[stop]
            stop = stop

            if stop > self.stop:
                raise IndexError
            if start < self.start:
                raise IndexError
            return Xrange(start, stop, step)

    def index(self, value):
        error = ValueError('object.index({0}): {0} not in object'.format(value))
        index = (value - self.start)/self.step
        if index % 1 != 0:
            raise error
        index = int(index)


        try:
            self.xrange[index]
        except (IndexError, TypeError):
            raise error
        return index

    def __len__(self):
        return len(self.xrange)
Python 2.7.3 (default, Jul 13 2012, 22:29:01) 
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> range(123456787676676767676676,123456787676676767676679)
[123456787676676767676676L, 123456787676676767676677L, 123456787676676767676678L]
>>> xrange(123456787676676767676676,123456787676676767676679)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: Python int too large to convert to C long
Python 3.2.3 (default, Jul 14 2012, 01:01:48) 
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> range(123456787676676767676676,123456787676676767676679)
range(123456787676676767676676, 123456787676676767676679)
>>> zip(range(5), xrange(100000000))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
In [1]: range(1,10)
Out[1]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

In [2]: xrange(10)
Out[2]: xrange(10)

In [3]: print xrange.__doc__
Out[3]: xrange([start,] stop[, step]) -> xrange object
import timeit
# Try various list sizes.
for list_len in [1, 10, 100, 1000, 10000, 100000, 1000000]:
  # Time doing a range and an xrange.
  rtime = timeit.timeit('a=0;\nfor n in range(%d): a += n'%list_len, number=1000)
  xrtime = timeit.timeit('a=0;\nfor n in xrange(%d): a += n'%list_len, number=1000)
  # Print the result
  print "Loop list of len %d: range=%.4f, xrange=%.4f"%(list_len, rtime, xrtime)
Loop list of len 1: range=0.0003, xrange=0.0003
Loop list of len 10: range=0.0013, xrange=0.0011
Loop list of len 100: range=0.0068, xrange=0.0034
Loop list of len 1000: range=0.0609, xrange=0.0438
Loop list of len 10000: range=0.5527, xrange=0.5266
Loop list of len 100000: range=10.1666, xrange=7.8481
Loop list of len 1000000: range=168.3425, xrange=155.8719