为什么或者为什么不呢?


当前回答

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

迭代时使用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

其他回答

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

迭代时使用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

书中给出了一个很好的例子:Practical Python By Magnus Lie Hetland

>>> zip(range(5), xrange(100000000))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]

我不建议在前面的例子中使用range而不是xrange——尽管如此 只需要前五个数字,range计算所有数字,这可能需要很多时间 的时间。使用xrange,这不是问题,因为它只计算所需的数字。

是的,我读了@Brian的回答:在python 3中,range()是一个生成器,xrange()不存在。

Range()返回列表,xrange()返回xrange对象。

Xrange()更快一点,内存效率更高一点。但是收益不是很大。

列表使用的额外内存当然不仅仅是浪费,列表有更多的功能(切片、重复、插入……)。具体的区别可以在文档中找到。没有硬性规定,需要什么就用什么。

Python 3.0仍在开发中,但IIRC range()将非常类似于xrange()的2。X和list(range())可以用来生成列表。

我只是想说,获得一个具有切片和索引功能的xrange对象真的不是那么困难。我写了一些代码,工作得很好,就像xrange一样快,当它计数(迭代)。

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)

老实说,我认为整个问题有点傻,xrange应该做所有这些…

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

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