显然 xrange 更快,但我不知道为什么它更快(除了轶事之外没有证据证明它更快)或者除此之外还有什么不同
for i in range(0, 20):
for i in xrange(0, 20):
在 Python 2.x 中:
range 创建一个列表,因此如果您执行 range(1, 10000000) 它会在内存中创建一个包含 9999999 个元素的列表。
xrange 是一个惰性求值的序列对象。
在 Python 3 中:
range 相当于 Python 2 的 xrange。要获取列表,您必须显式使用 list(range(...))。
xrange 不再存在。
range 创建一个列表,因此如果您执行 range(1, 10000000) 它会在内存中创建一个包含 9999999 个元素的列表。 xrange 是一个生成器,因此它是一个序列对象,是一个懒惰地评估的对象。
确实如此,但在 Python 3 中,range()
将由 Python 2 xrange()
实现。如果您需要实际生成列表,则需要执行以下操作:
list(range(1,100))
next(range(42))
)。
请记住,使用 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()
无论如何都会为您提供良好的迭代器行为。
python -m timeit "for i in xrange(1000000):" " pass"
the extra overhead is only 0.04 seconds
不是正确的看待它的方式,(90.5-51.1)/51.1 = 1.771 times slower
是正确的,因为它表明如果这是你程序的核心循环,它可能会成为瓶颈。但是,如果这是一小部分,那么 1.77x 就不算多。
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
不 返回迭代器。
and only keeps one number in memory at a time
,其余的放在哪里,请指导我..
一定要花一些时间在 Library Reference 上。您对它越熟悉,就越能更快地找到此类问题的答案。尤其重要的是关于内置对象和类型的前几章。
xrange 类型的优点是 xrange 对象将始终占用相同数量的内存,无论它表示的范围大小如何。没有一致的性能优势。
另一种快速查找有关 Python 构造信息的方法是文档字符串和帮助函数:
print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
doc 清楚地显示:
此函数与 range() 非常相似,但返回的是 xrange 对象而不是列表。这是一种不透明的序列类型,它产生与相应列表相同的值,但实际上并没有同时存储它们。 xrange() 相对于 range() 的优势是最小的(因为 xrange() 在被要求时仍然必须创建值),除非在内存不足的机器上使用非常大的范围或当范围的所有元素都是从未使用过(例如当循环通常以 break 终止时)。
在这个简单的示例中,您会发现 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
,上面的示例并没有反映出任何更好的情况。
现在看下面的例子,与 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
,它已经创建了一个从 0 到 100000000(耗时)的列表,但 xrange
是一个生成器,它只根据需要生成数字,即如果迭代继续。
在 Python-3 中,range
功能的实现与 Python-2 中的 xrange
相同,而在 Python-3 中它们取消了 xrange
编码快乐!!
range 创建一个列表,因此如果您执行 range(1, 10000000) 它会在内存中创建一个包含 10000000 个元素的列表。 xrange 是一个生成器,因此它的评估是惰性的。
这给您带来了两个好处:
您可以迭代更长的列表而不会出现 MemoryError。由于它懒惰地解析每个数字,如果您提前停止迭代,您将不会浪费时间创建整个列表。
这是出于优化的原因。
range() 将创建一个从开始到结束的值列表(在您的示例中为 0 .. 20)。这将成为非常大范围的昂贵操作。
另一方面, xrange() 更加优化。它只会在需要时(通过 xrange 序列对象)计算下一个值,并且不会像 range() 那样创建所有值的列表。
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
如果您使用 for
循环,range(x,y)
会返回 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
使用循环时没有太大区别,但仅打印时有区别!
其他一些答案提到 Python 3 消除了 2.x 的 range
并将 2.x 的 xrange
重命名为 range
。但是,除非您使用的是 3.0 或 3.1(没有人应该使用),否则它实际上是一种不同的类型。
正如 the 3.1 docs 所说:
Range 对象的行为很少:它们只支持索引、迭代和 len 函数。
但是,在 3.2+ 中,range
是一个完整序列——它支持扩展切片,并且 collections.abc.Sequence
的所有方法与 list
具有相同的语义。*
而且,至少在 CPython 和 PyPy(目前仅有的两个 3.2+ 实现)中,它还具有 index
和 count
方法和 in
运算符的常量时间实现(只要您只通过它是整数)。这意味着在 3.2+ 中写 123456 in r
是合理的,而在 2.7 或 3.1 中这将是一个可怕的想法。
* issubclass(xrange, collections.Sequence)
在 2.6-2.7 和 3.0-3.1 中返回 True
的事实是 a bug 在 3.2 中已修复且未向后移植。
在 python 2.x 中
range(x) 返回一个列表,该列表在内存中使用 x 个元素创建。
>>> a = range(5)
>>> a
[0, 1, 2, 3, 4]
xrange(x) 返回一个 xrange 对象,它是一个生成器 obj,它根据需要生成数字。它们是在 for 循环(惰性评估)期间计算的。
对于循环,这比 range() 稍快,并且内存效率更高。
>>> b = xrange(5)
>>> b
xrange(5)
xrange()
不是生成器。 xrange(n)
.__iter__()` 是。
在循环中针对 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 实例有何评论?或者一个更好的例子:-)
xrange
似乎稍微快一些,尽管现在使用 Python 3 进行比较是多余的。
timeit
的用途。它负责多次运行、禁用 GC、使用最佳时钟而不是 time
等。
python 中的 xrange() 和 range() 的工作方式与 user 类似,但是当我们讨论使用这两个函数时如何分配内存时,区别就来了。
当我们使用 range() 时,我们为它生成的所有变量分配内存,因此不建议使用较大的 no。要生成的变量。
另一方面,xrange() 一次只生成一个特定的值,并且只能与 for 循环一起使用以打印所需的所有值。
range 生成整个列表并返回它。 xrange 不会——它会按需生成列表中的数字。
xrange 使用迭代器(动态生成值), range 返回一个列表。
什么?
range
在运行时返回一个静态列表。
xrange
返回一个 object
(它的作用类似于一个生成器,虽然它肯定不是一个),在需要时从中生成值。
什么时候用哪个?
如果你想为一个巨大的范围(比如 10 亿)生成一个列表,请使用 xrange,尤其是当你有一个像手机这样的“内存敏感系统”时。
如果要多次迭代列表,请使用范围。
PS:Python 3.x 的 range
函数 == Python 2.x 的 xrange
函数。
xrange
不返回生成器对象。
每个人都已经解释得很清楚了。但我想让它亲眼看到。我使用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()”。
来自帮助文档。
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
。
range()
在 Python 中2.x
此函数本质上是 Python 2.x
中可用的旧 range()
函数,并返回包含指定范围内元素的 list
对象的实例。
但是,在初始化具有一系列数字的列表时,这种实现效率太低了。例如,for i in range(1000000)
在内存和时间使用方面都是一个非常昂贵的命令,因为它需要将此列表存储到内存中。
range()
在 Python 中 3.x
和 xrange()
在 Python 中 2.x
Python 3.x
引入了新的 range()
实现(而新的实现已经在 Python 2.x
中通过 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'>
关于扫描/打印 0-N 个项目的要求,range 和 xrange 的工作方式如下。
range() - 在内存中创建一个新列表并获取整个 0 到 N 项(总共 N+1)并打印它们。 xrange() - 创建一个迭代器实例,它扫描项目并仅将当前遇到的项目保留在内存中,因此始终使用相同数量的内存。
如果所需元素位于列表的开头,那么它可以节省大量时间和内存。
xrange
不创建迭代器实例。它创建一个 xrange
对象,该对象是可迭代的,但不是迭代器——几乎(但不完全是)一个序列,如列表。
Range 返回一个列表,而 xrange 返回一个 xrange 对象,该对象占用相同的内存,而与范围大小无关,因为在这种情况下,每次迭代只生成一个元素并且可用,而在使用范围的情况下,所有元素都会一次生成并且在内存中可用。
对于 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%。
range :-range 将一次填充所有内容。这意味着范围的每个数字都将占用内存。
xrange :-xrange 类似于生成器,当您想要数字范围但不希望存储它们时,它会出现,就像您想在 for 循环中使用时一样。所以内存效率高。
此外,如果做 list(xrange(...))
将等效于 range(...)
。
所以 list
很慢。
此外 xrange
确实没有完全完成序列
所以这就是为什么它不是一个列表,它是一个 xrange
对象
请参阅此 post 以找出 range 和 xrange 之间的区别:
去引用:
range 返回的正是你所想的:一个连续整数的列表,定义的长度从 0 开始。然而,xrange 返回一个“xrange 对象”,它的作用很像迭代器
xrange
不是迭代器。 range
返回的列表确实支持迭代(列表几乎是可迭代的原型示例)。 xrange
的整体好处不是“最小的”。等等。
i
都是根据需要而不是初始化进行评估的。