“收益项目”与返回iter(项目)有什么好处?

时间:2011-06-03 19:14:39

标签: python unit-testing iterator yield

在下面的示例中,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()“更灵活,但不经常使用”,但在版本2中返回iter(items)与yield的优缺点是什么?

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

5 个答案:

答案 0 :(得分:4)

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

更好的思考方法是使用ifilter(来自itertools),其中除了生成迭代器而不是生成器之外,你做的与yield相同:

 ifilter(process, resp.results)

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

答案 1 :(得分:4)

如果需要,可以很容易地将迭代器或生成器重新打开到列表中:

results = [item for item in iterator]

或者正如评论中所指出的那样,一种更简单的方法:

results = list(iterator)

答案 2 :(得分:3)

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

查看生成器http://www.dabeaz.com/generators/Generators.pdf

中的优秀文章

答案 3 :(得分:2)

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

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

答案 4 :(得分:1)

前代码段的pro con是所有结果都是预先计算出来的。如果检索每个项目之间的时间至关重要,但如果可迭代是无限的,或者如果空间是一个问题,那么这将是有用的。