"yield item" vs 返回迭代器(项目)的优势是什么?



在下面的示例中,resp.results是一个迭代器。

版本1:

items = []
for result in resp.results:
     item = process(result)
     items.append(item)
return iter(items)

版本2:

for result in resp.results:
     yield process(result)

在版本1中返回iter(项)在性能/内存节省方面是否比简单地返回项更好/更差?

在"Python Cookbook"中,Alex说显式iter()"更灵活,但使用频率较低",但返回iter(items)与版本2中的yield有什么利弊?

此外,对迭代器和/或yield进行单元测试的最佳方法是什么?——你不能做len(结果)来检查列表的大小吗?

如果需要,可以很容易地将迭代器或生成器返回到列表中:

results = [item for item in iterator]

或者,正如评论中善意指出的,一种更简单的方法:

results = list(iterator)

第一个导致计算并存储所有结果,而第二个是延迟加载,因此只有在请求时才计算结果。也就是说,一个将存储并创建N个项目的列表,而另一个将保存并创建0个项目,直到您开始迭代它们。

考虑这一点的一个更好的方法是使用ifilter(来自itertools),其中除了生成迭代器而不是生成器之外,您所做的与yield几乎相同:

 ifilter(process, resp.results)

我发现迭代器通常比2.x系列中的生成器执行得更快,但我无法验证3.x系列中有任何成本节约。

当您处理一个非常大的列表时,yield item会更好,因为它不会消耗太多内存。

在生成器中查看优秀文章http://www.dabeaz.com/generators/Generators.pdf

您可以创建无限迭代器,但不能创建无限列表:

def fibGen():
    f0, f1 = 0, 1
    while True:
        yield f0
        f0, f1 = f1, f0+f1

前一个片段的优点是所有结果都是预先计算的。如果检索每个项之间的时间很关键,这很有用,但如果可迭代性是无限的或空间是一个问题,这就不起作用。

相关内容

最新更新