显然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):
在 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))
typing.*
)。 - McSinyxnext(range(42))
)。 - McSinyx记住,使用 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"
。 - stalkrange
唯一的优点是如果你觉得它比xrange
更易读,或者你确实需要一个列表。此外,在您的计算机上运行timeit很可能无法反映您的代码将要运行的环境,并且无法告诉您内存方面的影响。 - TM.xrange
仅存储范围参数并根据需要生成数字。但是,Python的C实现目前将其参数限制为C长整型:
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
不返回迭代器。 - abarnert请务必花时间阅读库参考文献,你越熟悉它,就越能快速找到像这样的问题的答案。特别重要的是关于内置对象和类型的前几章。
xrange 类型的优势在于:不管所表示的范围大小,xrange 对象始终需要同样少的内存。但没有一致的性能优势。
另一种查找 Python 构造快速信息的方式是 docstring 和 help 函数:
print xrange.__doc__ # def doc(x): print x.__doc__ is super useful
help(xrange)
从文档中:
这个函数与
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
相比之下真的非常慢。
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
。
Happy Coding!
range 函数创建一个列表,所以如果你执行 range(1, 10000000),它会在内存中生成一个包含 10000000 个元素的列表。 xrange 是一个生成器,它会惰性地进行计算。
这带来了两个优点:
MemoryError
。这是出于优化的原因。
在你的例子中,range()会创建从开始到结束的值列表(0..20)。对于非常大的范围,这将成为一项昂贵的操作。
另一方面,xrange()更加优化。它只有在需要时才计算下一个值(通过xrange序列对象),不像range()那样创建所有值的列表。
i
都是按需求计算而不是在初始化时计算。 - Onilol