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

时间:2008-09-18 17:52:51

标签: python loops range python-2.x xrange

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

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

29 个答案:

答案 0 :(得分:750)

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

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

应该从@ Thiago的提示中添加,在python3中,范围相当于python的xrange

答案 1 :(得分:217)

  

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

     

xrange 是一个生成器,所以它是一个序列对象是一个,它懒惰地计算。

这是事实,但在Python 3中,{2} .range()将实现.xrange()。如果您需要实际生成列表,则需要执行以下操作:

list(range(1,100))

答案 2 :(得分:108)

请记住,使用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()无论如何都会给你很好的迭代器行为。

答案 3 :(得分:64)

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,但没有最小和最大端点的限制。

答案 4 :(得分:38)

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

答案 5 :(得分:28)

请花些时间在Library Reference上。你对它越熟悉,你就能越快找到这样的问题的答案。关于内置对象和类型的前几章特别重要。

  

xrange类型的优点是xrange对象总是如此   无论其代表的范围大小,都要占用相同数量的内存。   没有一致的性能优势。

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

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

答案 6 :(得分:13)

我很震惊没有人阅读doc

  

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

答案 7 :(得分:12)

  

范围创建一个列表,因此如果你执行范围(1,10000000),它会在内存中创建一个包含10000000个元素的列表。   xrange是一个生成器,因此它会懒惰地评估。

这为您带来两个好处:

  1. 您可以在不获取MemoryError的情况下迭代更长的列表。
  2. 由于它会懒散地解决每个数字,如果你提前停止迭代,你就不会浪费时间创建整个列表。

答案 8 :(得分:10)

出于优化原因。

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

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

答案 9 :(得分:10)

在这个简单示例中,您会发现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的情况下,上述示例并未反映出任何明显更好的内容。

现在看看以下rangexrange相比真的很慢的情况。

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的实现相同,而在Python-3中它们已经废除了xrange

快乐编码!!

答案 10 :(得分:8)

如果您使用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

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

答案 11 :(得分:8)

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

答案 12 :(得分:6)

在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)

答案 13 :(得分: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较慢的实例有何评论?或者更好的例子: - )

答案 14 :(得分:5)

其他一些答案提到Python 3取消了2.x&#39; range并将2.x&#39; s xrange重命名为range。但是,除非你使用3.0或3.1(没有人应该这样做),否则它实际上是一种不同的类型。

正如the 3.1 docs所说:

  

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

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

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

* 123456 in r在2.6-2.7和3.0-3.1中返回issubclass(xrange, collections.Sequence)的事实是a bug,已在3.2中修复且未向后移植。

答案 15 :(得分:4)

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

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

另一方面,

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

答案 16 :(得分:3)

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

答案 17 :(得分:3)

阅读以下文章,了解范围与xrange之间的比较,并进行图形分析。

Python range Vs xrange

答案 18 :(得分:2)

range()在Python 2.x

此函数本质上是Python range()中可用的旧2.x函数,它返回包含指定范围内元素的list对象的实例。

但是,当用一个数字范围初始化列表时,此实现效率太低。例如,就内存和时间使用而言,for i in range(1000000)的执行将是非常昂贵的命令,因为它需要将此列表存储到内存中。


range()在Python 3.xxrange()在Python 2.x

Python 3.x引入了range()的新实现(而新的实现已通过2.x函数在Python xrange()中提供)。

range()采用了称为惰性评估”的策略。与其创建大量范围内的元素,不如说,较新的实现引入了range类,这是一个轻量级的对象。表示给定范围内的必需元素,没有在内存中显式存储它们(这听起来像是生成器,但是惰性求值的概念有所不同)。


作为示例,请考虑以下内容:

# Python 2.x
>>> a = range(10)
>>> type(a)
<type 'list'>
>>> b = xrange(10)
>>> type(b)
<type 'xrange'>

# Python 3.x
>>> a = range(10)
>>> type(a)
<class 'range'>

答案 19 :(得分:2)

什么?
range在运行时返回静态列表 xrange会返回object(其作用类似于生成器,尽管它当然不是一个),在需要时会生成值。

何时使用哪个?

  • 如果您想生成一个巨大范围的列表,例如10亿,请使用xrange,尤其是当您拥有一个&#34;内存敏感系统时#34;就像手机一样。
  • 如果要多次遍历列表,请使用range

PS:Python 3.x&#39; range函数== Python 2.x&#39; xrange函数。

答案 20 :(得分:2)

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

答案 21 :(得分:1)

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%。

答案 22 :(得分:1)

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

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

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

答案 23 :(得分:1)

每个人都对此有很大的解释。但我希望它能为自己看到它。我用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,则将'range()'替换为第一个代码中的'xrange()',将'list(range())'替换为'range()'。

答案 24 :(得分:0)

范围会返回列表,而 xrange 会返回 xrange 对象,该对象会占用相同的内存而不管范围如何size,就像在这种情况下,每次迭代只生成一个元素并且可用,而在使用range的情况下,所有元素一次生成并在内存中可用。

答案 25 :(得分:0)

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

xrange:-xrange就像生成器一样,当你需要数字范围但是你不希望它们被存储时它会进入图片,就像你想要使用for loop.so内存效率一样。

答案 26 :(得分:0)

来自帮助文档。

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的xrangexrange被删除。

答案 27 :(得分:0)

此外,如果这样做,list(xrange(...))将等同于range(...)

所以list很慢。

xrange确实还没有完全完成序列

这就是为什么它不是列表,而是xrange对象的原因

答案 28 :(得分:-1)

请参阅此post以查找范围和xrange之间的差异:

引用:

  

range完全按照您的想法返回:连续列表   但是,以xrange开头的定义长度的整数   返回一个“xrange对象”,它像迭代器

一样发挥很大作用