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是一个生成器,所以懒惰地评估。
这带给你两个好处:
- 您可以迭代更长的列表而不会收到
MemoryError
。 - 由于它会懒散地解决每个数字,如果您提前停止迭代,则不会浪费时间创build整个列表。
我很震惊没有人阅读文档 :
这个函数与
range()
非常相似,但返回一个xrange
对象而不是一个列表。 这是一种不透明的序列types,与相应的列表产生相同的值,而不是实际同时存储它们。xrange()
优于range()
的优点是极小的(因为xrange()
在被要求的时候仍然需要创build值),除非在内存不足的机器上使用非常大的范围,或者当所有的范围元素都是从来没有使用过(比如当循环通常以break
结束时)。
这是为了优化的原因。
range()将创build一个从开始到结束的值列表(在你的例子中是0..20)。 这将成为一个非常大范围的昂贵的操作。
另一方面,xrange()更加优化。 它只会在需要的时候计算下一个值(通过一个xrange序列对象),并不会像range()那样创build所有值的列表。
在这个简单的例子中,你会发现超range
的xrange
的优点:
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+实现)中,它也有index
和count
方法的常量实现以及in
运算符(只要你只传递它的整数)。 这意味着123456 in r
写123456 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() –该函数返回可用于仅通过循环显示数字的生成器对象。 只有特定的范围按需显示,因此被称为“懒惰评估”。
两者都以不同的方式实施,并具有不同的特点。 比较的要点是:
- 返回types内存操作使用速度
- 记忆
- 操作使用
- 速度
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()更快。
重点:
- 如果你想编写在Python 2和Python 3上运行的代码,使用range()作为在Python 3中不推荐使用的xrange函数。
- 如果多次迭代相同的序列,range()会更快。
- xrange()必须每次重build整数对象,但range()将有实数整数对象。 (但内存方面总是会变差)。