为什么或者为什么不呢?


当前回答

这里的每个人对于xrange和range的利弊都有不同的看法。它们大多是正确的,xrange是一个迭代器,而range充实并创建了一个实际的列表。在大多数情况下,您不会真正注意到两者之间的区别。(你可以在range中使用map,但不能在xrange中使用,但这会占用更多内存。)

但是,我认为您可能希望听到的是首选的选项是xrange。由于Python 3中的range是一个迭代器,代码转换工具2to3将正确地将xrange的所有使用转换为range,并将抛出一个使用range的错误或警告。如果您希望确保将来可以轻松地转换代码,您将只使用xrange,当您确定需要一个列表时使用list(xrange)。我是在今年(2008年)芝加哥PyCon的CPython冲刺中了解到这一点的。

其他回答

虽然在大多数情况下xrange比range快,但性能上的差异非常小。下面的小程序比较了range和xrange的迭代:

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)

下面的结果显示xrange确实更快,但还不足以让人担心。

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

所以无论如何都要使用xrange,但除非您在受限的硬件上,否则不要太担心它。

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

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

You should favour range() over xrange() only when you need an actual list. For instance, when you want to modify the list returned by range(), or when you wish to slice it. For iteration or even just normal indexing, xrange() will work fine (and usually much more efficiently). There is a point where range() is a bit faster than xrange() for very small lists, but depending on your hardware and various other details, the break-even can be at a result of length 1 or 2; not something to worry about. Prefer xrange().

书中给出了一个很好的例子: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()不存在。

另一个区别是Python 2实现的xrange()不支持大于C int的数字,所以如果你想使用Python内置的大数字支持来获得一个范围,你必须使用range()。

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没有这个问题:

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)