你把几件事混在一起了。
def list_gen(n):
i=0
while i<n:
yield i
i += 1
这个函数是一个生成器。调用它会返回一个生成器对象,它是一个迭代器。
迭代器是具有 的事物next()
,即它可以被遍历一次。每当iter
您执行for i in something
.
def list_gen(n):
return range(n)
def list_gen(n):
return xrange(n)
这些函数是常规函数。一个返回一个list
,另一个返回一个xrange
对象。列表和 xrange 都是可迭代的,即可以为它们创建多个独立的迭代器。
所以回到你的问题:你问是返回一个list
还是一个xrange
对象。
这取决于,显然!这取决于你想对结果做什么。
如果你想以某种方式对其进行变异,那么你需要一个真实的列表。直接使用range
。
如果您只想迭代它,那么它在语义上并没有什么不同:xrange
对象和list
返回的对象range
都会产生一个迭代器,该迭代器迭代相同的序列。
但是,如果您使用xrange
,您将永远不会在内存中创建整个列表。list
如果你想做的只是一个简单的迭代,为什么还要在内存中创建一个成熟的对象呢?您不需要在需要for
循环时分配临时的大内存缓冲区,对吗?
因此:坚持使用 是安全的xrange
,因为调用者总是可以从中获利list
。
让我们用一个基准来确认这一点。我们想知道迭代 xranges 是否比迭代 by 构造的列表更快range
(当然包括range
调用成本)。
代码:
import timeit
ns = [1,2,3, 5, 10, 50, 100]
print 'n', '\t', 'range', '\t', 'xrange'
for n in ns:
t1 = timeit.timeit("for i in range({}): pass".format(n))
t2 = timeit.timeit("for i in xrange({}): pass".format(n))
print n, '\t', t1, '\t', t2
结果:
n range xrange
1 0.566222990493 0.418698436395
2 0.594136874362 0.477882061758
3 0.630704800817 0.488603362929
5 0.725149288913 0.540597548519
10 0.90297752809 0.687031507818
50 2.44493085566 1.89102105759
100 4.31189321914 3.33713522433