在许多情况下,人们总是说“使用yield
来惰性地创建元素”
但我认为一切都有代价,包括yield
和它的迭代器。
在有效的诺德眼中,我认为这是个好问题。
例如,当我得到一个函数时。
def list_gen(n):
if n > MAGIC_NUM:
return xrange(n)
else:
return range(n)
魔术师是多少钱?
更新对不起这个错误,我的起源意思是比较迭代器的成本和列表成本。
再次更新请成像一个案件。无论是否有条件,内存都会受到限制,以至于无法创建迭代器。
哈,这个问题现在更有趣了。
再次更新为什么创建迭代器和保存yield上下文要比创建列表少?或者迭代器要多少钱?(对不起我的侮辱)多少字节?
最佳答案
你把几件事搞混了。
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都是可iterable的,也就是说,可以为它们创建多个独立的迭代器。回到你的问题:你在问是返回一个
list
对象还是一个xrange
对象。显然,这要看情况!这取决于你想对结果做什么。
如果你想改变它,那么你需要一个真正的清单。直接使用
range
。如果您只想遍历它,那么它在语义上没有区别:一个
xrange
对象和一个list
返回的range
都将生成一个遍历同一序列的迭代器。但是,如果使用
xrange
,则永远不会在内存中创建整个列表。如果您只想做一个简单的迭代,为什么要在内存中创建一个完整的list
对象?您不需要在需要for
循环时分配临时的大内存缓冲区,对吧?因此:坚持使用
xrange
是安全的,因为来电者总是可以从中提取list
。让我们用一个基准来确认这一点。我们想知道在xranges上迭代是否比在由
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
关于python - 在Python中,何时 yield 成本超过返回列表?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13622551/