“yield item”和return iter(items)有什么优点?
下面的例子中,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)