Python 2. X中range和xrange函数有什么区别?

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

for i in range(0, 20):for i in xrange(0, 20):
464352 次浏览

查看此帖子以查找range和xrange之间的差异:

引述如下:

range准确地返回你的想法:一个连续的列表整数,定义的长度以0.xrange开头,但是,返回一个"xrange对象",它的作用非常像迭代器

xrange返回一个迭代器,一次只在内存中保存一个数字。范围将整个数字列表保存在内存中。

在Python 2. x中:

  • range创建一个列表,因此如果您执行range(1, 10000000),它会在内存中创建一个包含9999999元素的列表。

  • xrange是一个延迟计算的序列对象。

在Python 3中:

  • range相当于Python 2的xrange。要获取列表,您必须显式使用list(range(...))
  • xrange不再存在。

range生成整个列表并返回。xrange不会--它根据需要生成列表中的数字。

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

一定要花些时间在图书馆参考上。你对它越熟悉,你就能越快地找到这样的问题的答案。尤其重要的是关于内置对象和类型的前几章。

xrange类型的优点是xrange对象将始终取相同数量的内存,无论它代表的范围大小。没有一致的性能优势。

查找有关Python构造的快速信息的另一种方法是docstring和help函数:

print xrange.__doc__ # def doc(x): print x.__doc__ is super usefulhelp(xrange)

这是出于优化的原因。

range()将创建一个从头到尾的值列表(在您的示例中为0…20)。这将成为非常大范围的昂贵操作。

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

range创建一个列表,因此如果您执行range(1, 10000000),它会在内存中创建一个包含9999999元素的列表。

xrange是一个发电机,所以它是延迟计算的序列对象是一个

这是真的,但在Python 3中,range()将由Python 2xrange()实现。如果您需要实际生成列表,您需要执行:

list(range(1,100))

xrange仅存储范围参数并按需生成数字。然而,Python的C实现目前将其args限制为C long s:

xrange(2**32-1, 2**32+1)  # When long is 32 bits, OverflowError: Python int too large to convert to C longrange(2**32-1, 2**32+1)   # OK --> [4294967295L, 4294967296L]

请注意,在Python 3.0中只有range,它的行为类似于2. xxrange,但没有最小和最大终点的限制。

range创建一个列表,因此如果您执行range(1,10000000),它会在内存中创建一个包含10000000个元素的列表。Xrange是一个生成器,所以它会延迟计算。

这带给你两个好处:

  1. 您可以迭代更长的列表而不会得到MemoryError
  2. 由于它会懒惰地解析每个数字,如果您提前停止迭代,就不会浪费时间创建整个列表。

请记住,使用timeit模块来测试哪个小代码片段更快!

$ python -m timeit 'for i in range(1000000):' ' pass'10 loops, best of 3: 90.5 msec per loop$ python -m timeit 'for i in xrange(1000000):' ' pass'10 loops, best of 3: 51.1 msec per loop

就个人而言,我总是使用range(),除非我处理真的个巨大的列表——正如你所看到的,从时间上看,对于一个包含一百万个条目的列表,额外的开销只有0.04秒。正如Corey指出的那样,在Python 3.0中,xrange()将消失,range()无论如何都会给你很好的迭代器行为。

在循环中针对xrange测试range时(我知道我应该使用timeit,但这是使用一个简单的列表理解示例从内存中迅速破解的),我发现以下内容:

import time
for x in range(1, 10):
t = time.time()[v*10 for v in range(1, 10000)]print "range:  %.4f" % ((time.time()-t)*100)
t = time.time()[v*10 for v in xrange(1, 10000)]print "xrange: %.4f" % ((time.time()-t)*100)

其中规定:

$python range_tests.pyrange:  0.4273xrange: 0.3733range:  0.3881xrange: 0.3507range:  0.3712xrange: 0.3565range:  0.4031xrange: 0.3558range:  0.3714xrange: 0.3520range:  0.3834xrange: 0.3546range:  0.3717xrange: 0.3511range:  0.3745xrange: 0.3523range:  0.3858xrange: 0.3997 <- garbage collection?

或者,在for循环中使用xrange:

range:  0.4172xrange: 0.3701range:  0.3840xrange: 0.3547range:  0.3830xrange: 0.3862 <- garbage collection?range:  0.4019xrange: 0.3532range:  0.3738xrange: 0.3726range:  0.3762xrange: 0.3533range:  0.3710xrange: 0.3509range:  0.3738xrange: 0.3512range:  0.3703xrange: 0.3509

我的代码片段测试正确吗?对xrange的较慢实例有任何评论吗?或者一个更好的例子:-)

根据0-N项的扫描/打印要求,range和xrange的工作原理如下。

range()-在内存中创建一个新列表,并获取整个0到N个项目(总共N+1)并打印它们。xrange()-创建一个迭代器实例,该实例扫描项目并仅将当前遇到的项目保留到内存中,因此始终使用相同数量的内存。

如果所需的元素只是在列表的开头,那么它可以节省大量的时间和内存。

doc清楚地写着:

此函数与range()非常相似,但返回一个xrange对象而不是列表。这是一种不透明的序列类型,它产生与相应列表相同的值,而不是实际同时存储它们。xrange()相对于range()的优势很小(因为xrange()仍然必须在请求时创建值),除非在内存匮乏的机器上使用非常大的范围,或者该范围的所有元素从未使用过(例如循环通常以break终止)。

什么?
range在运行时返回一个静态列表。
xrange返回一个object(它就像一个生成器,尽管它肯定不是一个),在需要时从中生成值。

什么时候用哪个?

  • 如果你想为一个巨大的范围生成一个列表,比如10亿,特别是当你有一个像手机这样的“内存敏感系统”时,请使用xrange
  • 如果您想多次遍历列表,请使用range

PS:Python 3. x的range函数==Python 2. x的xrange函数。

范围返回列表,而xrange返回xrange对象,无论范围大小如何,它都占用相同的内存,因为在这种情况下,每次迭代只生成一个元素并且可用,而在使用范围的情况下,所有元素一次生成并且在内存中可用。

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

的3.1文档说:

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

但是,在3.2+中,range是一个完整的序列-它支持扩展切片,以及collections.abc.Sequence的所有方法与list具有相同的语义学。

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


*在2.6-2.7和3.0-3.1中,issubclass(xrange, collections.Sequence)返回True的事实是一个在3.2中修复的bug,而不是反向移植。

对于较小的参数,差异减小到range(..)/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%左右。

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

Python中的xrange()和range()与用户的工作方式类似,但当我们谈论使用这两个函数时如何分配内存时,差异就来了。

当我们使用range()时,我们为它生成的所有变量分配内存,因此不建议使用更大的数量。要生成的变量。

另一方面,xrange()一次只能生成一个特定的值,并且只能与for循环一起使用以打印所需的所有值。

在python 2. x中

范围(x)返回一个列表,该列表是在内存中使用x个元素创建的。

>>> a = range(5)>>> a[0, 1, 2, 3, 4]

xrange(x)返回一个xrange对象,它是一个生成器obj,它根据需要生成数字。它们在for循环(懒惰评估)期间计算。

对于循环,这比range()稍微快一点,内存效率更高。

>>> b = xrange(5)>>> bxrange(5)

如果您使用for循环,range(x,y)返回x和y之间的每个数字的列表,那么range会慢一些。事实上,range的索引范围更大。range(x.y)将打印出x和y之间所有数字的列表

xrange(x,y)返回xrange(x,y),但如果您使用for循环,则xrange更快。xrange的索引范围较小。xrange不仅会打印出xrange(x,y),还会保留其中的所有数字。

[In] range(1,10)[Out] [1, 2, 3, 4, 5, 6, 7, 8, 9][In] xrange(1,10)[Out] xrange(1,10)

如果你使用for循环,那么它会起作用

[In] for i in range(1,10):print i[Out] 123456789[In] for i in xrange(1,10):print i[Out] 123456789

使用循环时没有太大区别,尽管只是打印时有区别!

在这个简单的例子中,你会发现xrangerange的优势:

import timeit
t1 = timeit.default_timer()a = 0for i in xrange(1, 100000000):passt2 = timeit.default_timer()
print "time taken: ", (t2-t1)  # 4.49153590202 seconds
t1 = timeit.default_timer()a = 0for i in range(1, 100000000):passt2 = timeit.default_timer()
print "time taken: ", (t2-t1)  # 7.04547905922 seconds

上面的例子在xrange的情况下并没有更好地反映任何东西。

现在看看下面的例子,与xrange相比,range真的很慢。

import timeit
t1 = timeit.default_timer()a = 0for i in xrange(1, 100000000):if i == 10000:breakt2 = timeit.default_timer()
print "time taken: ", (t2-t1)  # 0.000764846801758 seconds
t1 = timeit.default_timer()a = 0for i in range(1, 100000000):if i == 10000:breakt2 = timeit.default_timer()
print "time taken: ", (t2-t1)  # 2.78506207466 seconds

使用range,它已经创建了一个从0到100000000的列表(耗时),但是xrange是一个生成器,它只根据需要生成数字,也就是说,如果迭代继续。

在Python-3中,range功能的实现与Python-2中的xrange相同,而他们在Python-3中取消了xrange

编码快乐!!

范围:-范围将填充所有内容once.which意味着范围的每个数字都将占用内存。

xrange:-xrange有点像生成器,当你想要数字的范围但不希望它们被存储时,它会出现在图片中,就像你想使用in来loop.so内存效率一样。

每个人都对它做了很多解释。但我想让它自己看。我使用python3。所以,我打开了资源监视器(在Windows中!),首先,执行以下命令:

a=0for i in range(1,100000):a=a+i

然后检查正在使用内存中的更改。这是微不足道的。然后,我运行以下代码:

for i in list(range(1,100000)):a=a+i

它立即占用了一大块内存。而且,我被说服了。你可以自己试试看

如果您使用的是Python 2X,请将第一段代码中的'range()'替换为'xrange()',并将'list(range())'替换为'range()'。

从帮助文档。

python2.7.12

>>> print range.__doc__range(stop) -> list of integersrange(start, stop[, step]) -> list of integers
Return a list containing an arithmetic progression of integers.range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.When step is given, it specifies the increment (or decrement).For example, range(4) returns [0, 1, 2, 3].  The end point is omitted!These are exactly the valid indices for a list of 4 elements.
>>> print xrange.__doc__xrange(stop) -> xrange objectxrange(start, stop[, step]) -> xrange object
Like range(), but instead of returning a list, returns an object thatgenerates the numbers in the range on demand.  For looping, this isslightly faster than range() and more memory efficient.

python3.5.2

>>> print(range.__doc__)range(stop) -> range objectrange(start, stop[, step]) -> range object
Return an object that produces a sequence of integers from start (inclusive)to stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.start defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.These are exactly the valid indices for a list of 4 elements.When step is given, it specifies the increment (or decrement).
>>> print(xrange.__doc__)Traceback (most recent call last):File "<stdin>", line 1, in <module>NameError: name 'xrange' is not defined

区别很明显。在Python 2. x中,range返回一个列表,xrange返回一个可迭代的xrange对象。

在Python 3. x中,range变为Python 2. x的xrangexrange被删除。

此外,if dolist(xrange(...))将等价于range(...)

所以list很慢。

而且xrange真的没有完全完成序列

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