在许多情况下,人们总是说“使用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/

10-11 13:06