【问题标题】:implicit memory consumption with itertools.tee of generators生成器的 itertools.tee 的隐式内存消耗
【发布时间】:2021-12-13 16:17:00
【问题描述】:

我正在使用来自herehere 的答案来检查我的生成器x 是否为空。

from itertools import tee
def my_generator():
    yield from range(100000000)
x = my_generator()
x, y = tee(x)
try:
    next(y)
except StopIteration:
    # x is empty do something
    quit()

x 中提取的元素会发生什么?他们可以被丢弃吗?还是必须保存在内存中以供y使用?

# now consume x entirely
for z in x:
    print(x)
# how can y iterate over its objects ?
# will they have to reside in memory now ??

【问题讨论】:

  • 你指的是什么y?你的意思是z?生成器“产生”的元素可以在使用后丢弃。生成器只是一个“惰性列表”,每次需要从中获取元素时都必须调用它。
  • @MortenJensen 谢谢,我修正了错字 - 问题是由于 x 和 y 现在都“依赖”于“x”,当它的元素“消失”时会发生什么?
  • 你的帖子仍然引用了y,这让我很困惑。生成器是一种“函数”,一次返回一个项目。当您完成对它们的迭代时,生成器“已用完”,您必须重新创建生成器以再次迭代项目集合。集合本身没有任何反应,生成器只是集合的抽象。

标签: python itertools


【解决方案1】:

tl;dr - 从x 产生的元素将保留在内存中,直到它们也从y 产生。

使用itertools.tee 时,必须为从tee 返回的所有迭代器保存所有生成元素的副本。 在您的情况下,它们是 xy

这样做是为了允许通过xy 进行完全迭代。

如果您查看Python docs for itertools.tee 中的等效实现,您可以看到所有生成的值都被保存,直到它们从返回的所有生成器tee 中生成。

在您的情况下,您必须同时使用 xy 或让它们(两者)超出范围并进行垃圾收集以释放项目。

【讨论】:

  • 我在 python 控制台中进行了测试,即使对象是从所有迭代器中产生的,它们也不会被破坏。它们仅在迭代器被删除时被销毁。我试过 gc.collect()
猜你喜欢
  • 2022-06-14
  • 1970-01-01
  • 2012-08-04
  • 1970-01-01
  • 1970-01-01
  • 2015-06-16
  • 2010-10-27
  • 2011-12-13
  • 2018-07-22
相关资源
最近更新 更多