irange()与range()或xrange()有何不同?
我在浏览Python生成器的维基百科时,发现了这个关于 RangeGenerator 的页面,里面提到了 irange()
。
这个功能可以让我们在处理大量数字时,不用使用xrange,因为xrange是一个懒惰的列表,而不是生成器。
我对页面上描述的测试套件和实现方式有点搞不懂。我知道 range()
会在内存中创建一个列表(从Python 2.7的角度看),而 xrange()
是一个生成器。那么 irange()
有什么不同呢?
2 个回答
irange 提供了一种生成器,它不会把所有的结果一次性加载到内存中。比如说,如果你用 range(1, 1000000)
,那么会把1000000个数字都加载到内存里,这样会占用很多空间。而如果你用 xrange(1, 1000000)
,那么每次只会在内存中保留一个数字,这样就节省了内存。
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