我看到它们产生相同的结果,是速度差异吗?为什么同一件事有两个功能?
> range(5)
[0, 1, 2, 3, 4]
>>> xrange(5)
xrange(5)
>>> for i in range(5):
... print i
...
0
1
2
3
4
>>> for i in xrange(5):
... print i
...
0
1
2
3
4
我看到它们产生相同的结果,是速度差异吗?为什么同一件事有两个功能?
> range(5)
[0, 1, 2, 3, 4]
>>> xrange(5)
xrange(5)
>>> for i in range(5):
... print i
...
0
1
2
3
4
>>> for i in xrange(5):
... print i
...
0
1
2
3
4
是的,
range
它们xrange
产生相同的结果,但方式不同。基地
您可能已经猜到了,该函数
range
返回一个列表:range 函数将根据您作为参数传递给它的范围的大小来占用内存量。
另一方面,该函数
xrange
返回它自己的数据类型,即xrange-type:好吧,背后没有太多科学
xrange
,实际上它在性能方面没有任何区别range
,优点是xrange
无论范围大小,它都会始终占用相同数量的内存(RAM):简而言之,这两个函数的最终目标都是返回列表,但我们可以说
xrange
它们是按需返回的,因为它们具有“惰性”特性。迭代器
在这两种情况下,都支持迭代协议,因为两者都有方法
__iter__
:所以以下情况是等价的:
这同样适用于
xr
。最大的区别在于,当你迭代时,r
你是在一个已经被评估过(并加载到内存中)的列表上做的,而当你迭代时,xr
你是在一个“惰性”列表上做的,它把值传递给你您需要它们(一次加载到内存中)。现在这对于 10 个整数的范围可能没有多大意义,但是尝试使用几百万个整数,您会发现 RAM 有所不同。
发电机
我知道这不是原始问题的一部分,但将它添加到答案中似乎是相关的,因为生成器是最终实现迭代协议的对象。
它们类似于列表推导式,但使用括号而不是方括号创建。
例子:
现在,生成器以类似的方式工作,
xrange
因为它们也是“惰性”的,并且只在您需要时返回值,而无需使用表达式将所有内容加载到内存中yield
。参考
该函数
range
生成一个逐项操作的内部临时列表,同时xrange
生成一个交互器(定义接口以遍历项的聚合并访问它们,以便客户端不必知道细节并能够处理它们无论如何)可以通过而无需花费可能是大型临时列表对象的费用。例子:
Stop
x
atrange(10000)
:它将生成一个包含10,000 个元素的列表,然后依次遍历每个元素。for
x
inxrange(10000)
:会一个一个生成1万个整数,依次传递给变量x。参考
在 python2 中,它们是不同的函数,它们的细微差别在xrange 文档中得到了很好的解释:它
xrange
生成一个xrange 对象,并range
生成一个列表。该对象的优点XRange
是它不需要在需要时生成所有元素,这意味着可以节省大量资源。此外,在CPython实现(这是最常见的 python)中,这种类型的循环可以被优化得更好、更简单。在 Python3 中不再有两个函数,统一为一个函数
range
,相当于xrange
python2 函数。要获取列表,需要调用列表构造函数(例如list(range(1000))
:)