irange()与range()或xrange()有何不同?

17 投票
2 回答
14473 浏览
提问于 2025-04-18 02:05

我在浏览Python生成器的维基百科时,发现了这个关于 RangeGenerator 的页面,里面提到了 irange()

这个功能可以让我们在处理大量数字时,不用使用xrange,因为xrange是一个懒惰的列表,而不是生成器。

我对页面上描述的测试套件和实现方式有点搞不懂。我知道 range() 会在内存中创建一个列表(从Python 2.7的角度看),而 xrange() 是一个生成器。那么 irange() 有什么不同呢?

2 个回答

-2

irange 提供了一种生成器,它不会把所有的结果一次性加载到内存中。比如说,如果你用 range(1, 1000000),那么会把1000000个数字都加载到内存里,这样会占用很多空间。而如果你用 xrange(1, 1000000),那么每次只会在内存中保留一个数字,这样就节省了内存。

28

irange() 返回的是一种生成器类型,这种类型只能被遍历一次。也就是说,你只能走一遍这个生成器,一旦走完了,就不能再走第二遍了。

Python 2 的 xrange() 类型 和 Python 3 的 range() 类型 是一种序列类型,它们支持很多其他序列也支持的操作,比如获取长度、检查某个值是否在里面,以及索引操作:

>>> xr = xrange(10, 20, 3)
>>> len(xr)
4
>>> 10 in xr
True
>>> xr[0]
10
>>> xr[1]
13

你可以多次遍历这些对象:

>>> for i in xr:
...     print i,
... 
10 13 16 19
>>> for i in xr:
...     print i,
... 
10 13 16 19

你甚至可以使用 reversed() 函数 来反向遍历它们,这样做也很高效:

>>> for i in reversed(xr):
...     print i,
... 
19 16 13 10

Python 3 的 range() 类型是 xrange() 的升级版,它支持更多的序列操作,效率更高,而且可以处理超出 sys.maxint 的值(在 Python 2 中,这个值对应于 long 整数)。

它支持切片操作,比如说,你可以对它进行切片,这样会得到一个新的 range() 对象,包含切片后的值:

>>> r = range(10, 20, 3)
>>> r[:2]
range(10, 16, 3)

你可以像对待其他 Python 序列一样使用负索引,从后往前获取元素:

>>> r[-2]
16
>>> r[-2:]
range(16, 22, 3)

这个类型还支持相等性测试;两个 range() 实例如果产生相同的值,它们就是相等的:

>>> range(10, 20, 3) == range(10, 21, 3)
True

在 Python 2 中,生成器 irange() 唯一的优势可能是它不受 xrange() 对非长整型的限制:

>>> import sys
>>> xrange(sys.maxint)
xrange(9223372036854775807)
>>> xrange(sys.maxint + 1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: Python int too large to convert to C long

撰写回答