显然xrange更快,但我不知道为什么它更快(除了目前为止的传闻之外,没有证据表明它更快),或者除此之外还有什么不同
for i in range(0, 20):
for i in xrange(0, 20):
显然xrange更快,但我不知道为什么它更快(除了目前为止的传闻之外,没有证据表明它更快),或者除此之外还有什么不同
for i in range(0, 20):
for i in xrange(0, 20):
当前回答
这是出于优化的原因。
range()将创建从开始到结束的值列表(示例中为0..20)。这将成为非常大范围的昂贵操作。
另一方面,xrange()更为优化。它只会在需要时(通过xrange序列对象)计算下一个值,不会像range()那样创建所有值的列表。
其他回答
range生成整个列表并返回它。xrange不——它根据需要生成列表中的数字。
Python 2.x中的range()
该函数本质上是Python2.x中可用的旧range()函数,并返回包含指定范围内元素的列表对象的实例。
然而,当使用一系列数字初始化列表时,这种实现效率太低。例如,对于范围(1000000)中的i,无论是在内存还是时间使用方面,都是一个非常昂贵的命令,因为它需要将这个列表存储到内存中。
Python 3.x中的range()和Python 2.x中的xrange()
Python3.x引入了一个新的range()实现(而新的实现已经在Python2.x中通过xrange()函数提供)。
range()利用了一种称为惰性求值的策略。新的实现没有在范围内创建一个庞大的元素列表,而是引入了类范围,这是一个轻量级对象,表示给定范围内所需的元素,而没有将它们显式存储在内存中(这听起来可能像生成器,但惰性求值的概念不同)。
例如,考虑以下内容:
# Python 2.x
>>> a = range(10)
>>> type(a)
<type 'list'>
>>> b = xrange(10)
>>> type(b)
<type 'xrange'>
and
# Python 3.x
>>> a = range(10)
>>> type(a)
<class 'range'>
当在一个循环中测试range和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的较慢实例有何评论?或者更好的例子:-)
记住,使用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返回一个列表。