使用嵌套迭代器有啥意义吗?

Posted

技术标签:

【中文标题】使用嵌套迭代器有啥意义吗?【英文标题】:Is there a point to using nested iterators?使用嵌套迭代器有什么意义吗? 【发布时间】:2014-11-17 04:51:32 【问题描述】:

我正在阅读我的一些旧代码并遇到了这一行

itertools.starmap(lambda x,y: x + (y,), 
                  itertools.izip(itertools.repeat(some_tuple, 
                                                  len(list_of_tuples)),
                                 itertools.imap(lambda x: x[0],
                                                list_of_tuples)))

需要明确的是,我有一些 list_of_tuples,我想从中取出每个元组的第一项(itertools.imap),我还有另一个我想重复的元组(itertools.repeat)这样是list_of_tuples 中每个元组的副本,然后我想根据list_of_tuples (itertools.starmap) 中的项目获得新的、更长的元组。

例如,假设some_tuple = (1, 2, 3)list_of_tuples = [(1, other_info), (5, other), (8, 12)]。我想要[(1, 2, 3, 1), (1, 2, 3, 5), (1, 2, 3, 8)] 之类的东西。这不是确切的 IO(它使用了一些非常不相关和复杂的类),而且我的实际列表和元组非常大。

这样嵌套迭代器有什么意义吗?在我看来,来自 itertools 的每个函数都必须遍历我给它的迭代器,并将其中的信息存储在某个地方,这意味着将其他迭代器放在 starmap 内没有任何好处。我完全错了吗?这是如何工作的?

【问题讨论】:

如果您向我们展示预期的输入和输出将很好地映射您的工作 不,原因很简单,它使代码难以理解。保持简单 @gnibbler 可能是这样,即使删除它仍然会得到我们嵌套的迭代器,所以除非删除它会改变答案,否则我仍然想知道是否有一般嵌套的意义 @Dannnno,如果你真的很小心,使用 itertools 可以获得性能提升。不过这里不太可能是这种情况。 【参考方案1】:

没有理由嵌套迭代器。使用变量不会对性能/内存产生明显影响:

first_items = itertools.imap(lambda x: x[0], list_of_tuples)
repeated_tuple = itertools.repeat(some_tuple, len(list_of_tuples))
items = itertools.izip(repeated_tuple, first_items)
result = itertools.starmap(lambda x,y: x + (y,), items)

itertools 使用和返回的迭代器对象不会将所有项存储在内存中,而只是在需要时计算下一项。您可以阅读更多关于它们如何工作的信息here。

【讨论】:

我认为这正是我的问题所要问的。我不确定如果不嵌套迭代器,我最终会在内存中存储比我想要的更多的东西。谢谢!【参考方案2】:

我不认为在这种情况下上述组合是必要的。

它似乎等同于这个生成器表达式:

(some_tuple + (y[0],) for y in list_of_tuples)

然而,itertools 有时会具有性能优势,尤其是在 cpython 中

【讨论】:

所以忽略我给出的例子,我可以看到这不是一个好的例子,一般来说,迭代器的嵌套会对程序的性能产生任何积极的或其他的影响吗?还是必须根据具体情况来决定? @Dannnno,您应该更喜欢以最易读的方式编写代码。如果它被证明是一个性能瓶颈,你可以用任何你认为更快的方式重写它。保留易于阅读的版本作为文档。您可以针对这两个版本编写单元测试,以检测行为是否在您的更快版本中意外更改

以上是关于使用嵌套迭代器有啥意义吗?的主要内容,如果未能解决你的问题,请参考以下文章

python中的迭代器有啥用

通过引用传递 C++ 迭代器有啥问题?

我应该使用迭代器还是 for 循环来迭代?

使用对象初始化器有啥好处吗?

python 生成器和迭代器有这篇就够了

迭代器的解释