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

显然xrange是更快,但我不知道为什么它更快(除了轶事迄今没有证据,它是更快),或除此之外是什么不同

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

范围创build一个列表,所以如果你做range(1, 10000000)它会在内存中创build一个包含9999999元素的列表。

xrange是一个懒惰评估的序列对象。

范围创build一个列表,所以如果你做range(1, 10000000)它会在内存中创build一个包含9999999元素的列表。

xrange 是一个生成器,所以它是一个序列对象是一个懒惰的评估。

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

 list(range(1,100)) 

请记住,使用timeit模块来testing哪些小代码更快!

 $ 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将会消失,范围无论如何会给你带来更好的迭代器行为。

xrange只存储范围参数并根据需要生成数字。 然而,Python的C实现目前将其参数限制为C long:

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

请注意,在Python 3.0中,只有range ,其行为与2.x xrange相似,但对最小和最大端点没有限制。

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

请花一些时间与图书馆参考 。 你对它越熟悉,就能越快find这样的问题的答案。 特别重要的是关于内build对象和types的前几章。

xrangetypes的优点是xrange对象将总是占用相同数量的内存,而不pipe它所代表的范围的大小。 没有一致的性能优势。

另一种查找有关Python构造的快速信息的方法是文档string和帮助function:

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

范围创build一个列表,所以如果你做范围(1,10000000),它会在内存中创build一个10000000个元素的列表。 xrange是一个生成器,所以懒惰地评估。

这带给你两个好处:

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

我很震惊没有人阅读文档 :

这个函数与range()非常相似,但返回一个xrange对象而不是一个列表。 这是一种不透明的序列types,与相应的列表产生相同的值,而不是实际同时存储它们。 xrange()优于range()的优点是极小的(因为xrange()在被要求的时候仍然需要创build值),除非在内存不足的机器上使用非常大的范围,或者当所有的范围元素都是从来没有使用过(比如当循环通常以break结束时)。

这是为了优化的原因。

range()将创build一个从开始到结束的值列表(在你的例子中是0..20)。 这将成为一个非常大范围的昂贵的操作。

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

在这个简单的例子中,你会发现超rangexrange的优点:

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

上面的例子在xrange情况下并没有反映出任何实质上的好处。

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

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

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

在Python-3中, range函数的实现与Python-2中的xrange的实现相同,但是他们已经在Python-3中取消了xrange

快乐编码!

范围():范围(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(x,y)返回x和y之间的每个数字的列表,如果使用for循环,则range更慢。 事实上, range有一个更大的指数范围。 range(xy)将打印出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] 1 2 3 4 5 6 7 8 9 [In] for i in xrange(1,10): print i [Out] 1 2 3 4 5 6 7 8 9 

使用循环的时候没有太大的区别,只是在打印时有区别!

其他一些答案提到,Python 3消除了2.x的range ,并将2.x的xrange重新命名为range 。 但是,除非你使用3.0或3.1(没有人应该),它实际上是一个不同的types。

正如3.1文档所说:

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

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

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


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

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

当我们使用range()为所有正在生成的variables分配内存时,build议不要使用更大的no。 要生成的variables。

另一方面,xrange()一次只能生成一个特定的值,只能用for循环来打印所有需要的值。

在Python 2.x

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

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

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

对于循环来说,这比range()要快一些,并且有更高的内存效率。

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

当在一个循环中testing范围与xrange(我知道我应该使用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.py range: 0.4273 xrange: 0.3733 range: 0.3881 xrange: 0.3507 range: 0.3712 xrange: 0.3565 range: 0.4031 xrange: 0.3558 range: 0.3714 xrange: 0.3520 range: 0.3834 xrange: 0.3546 range: 0.3717 xrange: 0.3511 range: 0.3745 xrange: 0.3523 range: 0.3858 xrange: 0.3997 <- garbage collection? 

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

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

我的代码段是否正确testing? 有关xrange的较慢实例的任何意见? 或者更好的例子:-)

范围生成整个列表并返回它。 xrange不会 – 它会根据需求在列表中生成数字。

用graphics分析阅读下面的范围和xrange之间的比较。

Python范围VS xrange

xrange使用迭代器(即时生成值),范围返回一个列表。

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

什么时候用哪个?

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

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

在要求扫描/打印0-N项目时,范围和xrange的工作如下。

范围() – 在内存中创build一个新的列表,并将整个0到N个项目(总共N + 1)打印出来。 xrange() – 创build一个迭代器实例,扫描项目并只保留当前遇到的项目到内存中,因此总是使用相同数量的内存。

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

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

看到这个postfind范围和xrange之间的区别:

去引用:

range正好返回你所想象的:连续整数的列表,一个以0开始的定义长度。然而, xrange返回一个“xrange对象” ,它像一个迭代器

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

范围:-range将立即填充所有内容,这意味着范围的每个数字将占用内存。

xrange:-xrange是类似于generator的东西,当你想要数字的范围,但是你不希望它们被存储的时候,它就会进入图像,就像当你想用于循环的时候一样。

大家都解释得很清楚 但我想让它自己看。 我使用python3。 所以,我打开了资源监视器(在Windows中!),首先执行下面的命令:

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

然后检查“正在使用”内存中的更改。 这是微不足道的。 然后,我跑了下面的代码:

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

而且它立即使用了大量的内存。 而且,我确信。 你可以自己尝试。

如果你正在使用Python 2X,那么用第一个代码中的'xrange()'和'range()'中的'list(range())'replace'range()'。

从帮助文档。

Python 2.7.12

 >>> print range.__doc__ range(stop) -> list of integers range(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 object xrange(start, stop[, step]) -> xrange object Like range(), but instead of returning a list, returns an object that generates the numbers in the range on demand. For looping, this is slightly faster than range() and more memory efficient. 

Python 3.5.2

 >>> print(range.__doc__) range(stop) -> range object range(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的xrange ,并且xrange被移除。

范围()与xrange()在Python中:

range()和xrange()是两个函数,可用于在Python中for循环中迭代若干次。 在Python 3中,没有xrange,但范围函数的行为与Python 2中的xrange相同。如果要编写将在Python 2和Python 3上运行的代码,则应使用range()。

range() –这将返回使用range()函数创build的数字列表。

xrange() –该函数返回可用于仅通过循环显示数字的生成器对象。 只有特定的范围按需显示,因此被称为“懒惰评估”。

两者都以不同的方式实施,并具有不同的特点。 比较的要点是:

  1. 返回types内存操作使用速度
  2. 记忆
  3. 操作使用
  4. 速度

1.返回types:

范围()返回 –列表作为返回types。

xrange()返回 – xrange()对象。

 # initializing a with range() a = range(1,10000) # initializing a with xrange() x = xrange(1,10000) # testing the type of a print ("The return type of range() is : ") print (type(a)) # testing the type of x print ("The return type of xrange() is : ") print (type(x)) 

输出:

 The return type of range() is : <type 'list'> The return type of xrange() is : <type 'xrange'> 

2.内存:

与使用xrange()存储范围的variables相比,存储由range()创build的范围的variables需要更多的内存。 其基本原因是范围()的返回types是list,而xrange()是xrange()对象。

 # initializing a with range() a = range(1,10000) # initializing a with xrange() x = xrange(1,10000) # testing the size of a print ("The size allotted using range() is : ") print (sys.getsizeof(a)) # testing the size of a print ("The size allotted using xrange() is : ") print (sys.getsizeof(x)) 

输出:

 The size allotted using range() is : 80064 The size allotted using xrange() is : 40 

3.操作使用情况:

当range()返回列表时,可以在列表上使用列表上可以应用的所有操作。 另一方面,当xrange()返回xrange对象时,与列表关联的操作不能应用于它们,因此是缺点。

 # Python code to demonstrate range() vs xrange() # on basis of operations usage # initializing a with range() a = range(1,6) # initializing a with xrange() x = xrange(1,6) # testing usage of slice operation on range() print ("The list after slicing using range is : ") print (a[2:5]) # testing usage of slice operation on xrange() print ("The list after slicing using xrange is : ") print (x[2:5]) 

输出:

 The list after slicing using range is : [3, 4, 5] The list after slicing using xrange is : Traceback (most recent call last): File "pp.py", line 18, in <module> print (x[2:5]) TypeError: sequence index must be integer, not 'slice' 

4.速度:

由于xrange()仅评估仅包含惰性评估所需的值的生成器对象,因此实现比range()更快。

重点:

  1. 如果你想编写在Python 2和Python 3上运行的代码,使用range()作为在Python 3中不推荐使用的xrange函数。
  2. 如果多次迭代相同的序列,range()会更快。
  3. xrange()必须每次重build整数对象,但range()将有实数整数对象。 (但内存方面总是会变差)。