“yield item”和return iter(items)有什么优点?

6 投票
5 回答
4153 浏览
提问于 2025-04-16 18:55

下面的例子中,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(items) 在性能和内存节省方面,和直接返回 items 比起来,有什么好处或坏处吗?

在《Python Cookbook》这本书中,Alex 说使用明确的 iter() 是“更灵活但不常用”,那么返回 iter(items) 和像版本2那样使用 yield 各自的优缺点是什么呢?

另外,测试一个迭代器和/或 yield 的最佳方法是什么?因为你不能用 len(results) 来检查列表的大小?

5 个回答

3

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

可以看看这篇关于生成器的优秀文章: http://www.dabeaz.com/generators/Generators.pdf

4

第一个方法会一次性计算出所有结果并把它们存储起来,而第二个方法则是懒加载,只有在需要的时候才会计算结果。也就是说,第一个方法会一次性生成N个项目的列表,而第二个方法在你开始遍历这些项目之前不会生成任何项目。

更好的理解方式是使用ifilter(来自itertools),它的工作方式和yield很相似,不过它生成的是一个迭代器,而不是生成器:

 ifilter(process, resp.results)

我发现,在2.x版本中,迭代器的执行速度通常比生成器快,但我无法确认在3.x版本中是否也有这样的节省。

4

如果你需要的话,把一个迭代器或者生成器转换回列表其实很简单:

results = [item for item in iterator]

或者正如评论中友好地指出的,还有一种更简单的方法:

results = list(iterator)

撰写回答