显然xrange更快但我不知道为什么它更快(除了轶事到目前为止没有证据表明它更快)或者除此之外还有什么不同
for i in range(0, 20): for i in xrange(0, 20):
小智.. 782
range创建一个列表,所以如果你这样做range
,就会在内存中用range(1, 10000000)
元素创建一个列表.
9999999
是一个懒惰评估的序列对象.
它应该从@Thiago的提示中添加,在python3中,范围相当于python的xrange
range创建一个列表,所以如果你这样做range
,就会在内存中用range(1, 10000000)
元素创建一个列表.
9999999
是一个懒惰评估的序列对象.
它应该从@Thiago的提示中添加,在python3中,范围相当于python的xrange
range创建一个列表,所以如果你这样做
range(1, 10000000)
,就会在内存中用9999999
元素创建一个列表.
xrange
为发电机,所以它是一个序列对象是一个计算结果懒惰地.
这是事实,但在Python 3中,.range()
将由Python 2实现.xrange()
.如果您需要实际生成列表,则需要执行以下操作:
list(range(1,100))
请记住,使用该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
只存储范围参数并按需生成数字.但是,Python的C实现目前将其args限制为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返回一个迭代器,一次只在内存中保留一个数字.range将整个数字列表保存在内存中.
花一些时间阅读图书馆参考资料.你对它越熟悉,你就能越快找到这样的问题的答案.关于内置对象和类型的前几章特别重要.
xrange类型的优点是xrange对象总是占用相同数量的内存,无论它所代表的范围大小.没有一致的性能优势.
查找有关Python构造的快速信息的另一种方法是docstring和help-function:
print xrange.__doc__ # def doc(x): print x.__doc__ is super useful help(xrange)
range创建一个列表,因此如果你执行range(1,10000000),它会在内存中创建一个包含10000000个元素的列表.xrange是一个生成器,所以它懒惰地评估.
这为您带来两个好处:
您可以迭代更长的列表而无需获取MemoryError
.
由于它可以懒散地解析每个数字,如果您提前停止迭代,则不会浪费时间创建整个列表.
我很震惊没有人读过doc:
此函数非常类似于
range()
,但返回xrange
对象而不是列表.这是一个不透明的序列类型,它产生与相应列表相同的值,而不是实际同时存储它们.xrange()
过度的优势range()
是最小的(因为xrange()
在被要求时仍需要创建值)除非在内存不足的机器上使用非常大的范围或者从不使用所有范围的元素时(例如当循环是通常以...结束break
.
这是出于优化原因.
range()将从头到尾创建一个值列表(在您的示例中为0 .. 20).这将在非常大的范围内成为昂贵的操作.
另一方面,xrange()更加优化.它只会在需要时(通过xrange序列对象)计算下一个值,并且不会创建像range()那样的所有值的列表.
你会发现的优势xrange
超过range
在这个简单的例子:
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
.
现在看看以下情况,range
与之相比真的很慢xrange
.
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
它,它已经创建了一个从0到100000000(耗时)的列表,但它xrange
是一个生成器,它只根据需要生成数字,也就是说,如果迭代继续.
在Python-3中,range
功能的实现与Python-2中的实现相同xrange
,而它们xrange
在Python-3中已经废弃了
快乐编码!!
range(x,y)
如果使用for
循环,则返回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] 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
使用循环时没有太大区别,虽然只是打印时有区别!
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 2.x中
range(x)返回一个列表,该列表在内存中使用x元素创建.
>>> a = range(5) >>> a [0, 1, 2, 3, 4]
xrange(x)返回一个xrange对象,它是一个生成器obj,它根据需要生成数字.它们是在for-loop期间计算的(延迟评估).
对于循环,这比range()稍快,内存效率更高.
>>> b = xrange(5) >>> b xrange(5)
当在循环中测试范围对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
我的代码段测试是否正常?对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+实现)中,它还具有index
和count
方法和in
运算符的常量实现(只要你只传递整数).这意味着写作123456 in r
在3.2+中是合理的,而在2.7或3.1中则是一个可怕的想法.
*一个事实,issubclass(xrange, collections.Sequence)
返回True
在2.6-2.7 3.0-3.1和是一个错误是固定在3.2,而不是向后移植.