在下面的示例中,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
前一个片段的优点是所有结果都是预先计算的。如果检索每个项之间的时间很关键,这很有用,但如果可迭代性是无限的或空间是一个问题,这就不起作用。