显然xrange更快,但我不知道为什么它更快(除了目前为止的传闻之外,没有证据表明它更快),或者除此之外还有什么不同

for i in range(0, 20):
for i in xrange(0, 20):

当前回答

xrange使用迭代器(动态生成值),range返回一个列表。

其他回答

其他一些答案提到Python 3消除了2.x的范围,并将2.x的xrange重命名为range。然而,除非您使用3.0或3.1(没有人应该使用),否则它实际上是一种不同的类型。

正如3.1文档所说:

范围对象的行为很少:它们只支持索引、迭代和len函数。

然而,在3.2+中,range是一个完整的序列,它支持扩展切片,以及collections.abc.sequence的所有方法,其语义与列表相同*

而且,至少在CPython和PyPy(目前仅有的两个3.2+实现)中,它还具有索引和计数方法以及in运算符的常量时间实现(只要只传递整数)。这意味着在r中写123456在3.2+中是合理的,而在2.7或3.1中则是一个糟糕的想法。


*issubclass(xrange,collections.Sequence)在2.6-2.7和3.0-3.1中返回True的事实是一个在3.2中修复的错误,而不是后端口。

range():range(1,10)返回从1到10个数字的列表&将整个列表保存在内存中。

xrange():与range()类似,但不是返回列表,而是返回一个对象,该对象根据需要生成范围内的数字。对于循环,这比range()稍快,内存效率更高。xrange()对象类似于迭代器,并根据需要生成数字。(懒惰的评估)

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__

xrange([start,] stop[, step]) -> xrange object

这是出于优化的原因。

range()将创建从开始到结束的值列表(示例中为0..20)。这将成为非常大范围的昂贵操作。

另一方面,xrange()更为优化。它只会在需要时(通过xrange序列对象)计算下一个值,不会像range()那样创建所有值的列表。

此外,if do list(xrange(…))将等同于range(…)。

所以列表很慢。

而且xrange确实没有完全完成序列

这就是为什么它不是一个列表,而是一个xrange对象

对于范围(..)/xrange(..)的较小参数,差异减小:

$ python -m timeit "for i in xrange(10111):" " for k in range(100):" "  pass"
10 loops, best of 3: 59.4 msec per loop

$ python -m timeit "for i in xrange(10111):" " for k in xrange(100):" "  pass"
10 loops, best of 3: 46.9 msec per loop

在这种情况下,xrange(100)的效率仅提高约20%。