python - 使用 itertools.tee 检查下一个元素时如何最小化空间成本?

标签 python python-itertools tee

我正在尝试使用 itertools.tee 来知道迭代器是否为空而不完全消耗它:

from itertools import tee
def get_iterator(i):
    i1, i2 = tee(i, 2)
    if next(i1, None) is None:
       # iterator is empty - raises some error
       pass
    return i2 # return not empty iterator to caller

作为docs开球状态:

This itertool may require significant auxiliary storage (depending on how much temporary data needs to be stored). In general, if one iterator uses most or all of the data before another iterator starts, it is faster to use list() instead of tee().

所以很明显,当 i 不为空时,i2 在 i1 之前使用大部分数据。 一个简单的 del 可以解决这个问题吗?:

from itertools import tee
def get_iterator(i):
    i1, i2 = tee(i, 2)
    if next(i1, None) is None:
       # iterator is empty - raises some error
       pass
    del i1  # Does this overcome storage issue?
    return i2  # return not empty iterator to caller

有没有更好的方法来实现这个目标?

提前致谢!

最佳答案

这有点微妙 - 它取决于 tee 函数的一个未记录的属性以及 garbage collector 的一个故意模糊的属性.示例 Python 代码将存储从迭代器创建点到它们被每个迭代器使用的所有项,但人们可能很容易想象迭代器会产生清理效果,从而放弃对队列中数据的声明。但即便如此,del 还是删除了你的名字;它不保证对象的破坏。因此,这样的清理会起作用,但不一定会在您期望的时候起作用。知道这是否会发生需要阅读 the source code for tee .它确实有 weak reference对单个迭代器的支持,提出了一种可以完成此优化的方法。

tee_next 的 CPython 代码相当简单;它包含对 teedataobject 的引用,该对象最多包含 57 个项目,也形成一个单向链表。因此,正常的引用计数语义适用于该批处理级别。所以基本上,对于 CPython,即使它们已被所有迭代器消耗,最多 56 个项目仍保留在内存中,但仅此而已,因为引用计数处理是立即的。只要 tee 迭代器存在,它们之间的任意数量的项都可以保存,但它们不会从源迭代器中提前读取;至少有一个 tee 迭代器必须通过 teedataobject_getitem 获取了项目.

所以基本判断是:是的,del 将在 CPython 中工作,但使用 tee 意味着您临时存储 57 个项目的批处理,而不是 1 个。重复此操作方法可能会导致任意数量的此类窗口 - 除了 tee 迭代器是可复制的,并将共享它们的基础列表。

这是对CPython的一个版本(4243df51fe43)的具体解释。实现将有所不同,例如PyPy、IronPython、Jython 或其他版本的 CPython。

例如,PyPy's tee (版本 cadf868)使用类似的链表,每个链接一个项目,因此不会像此 CPython 版本那样进行批处理。

有一个显着的捷径可以防止这种成本增加:我检查过的两个 tee 实现都产生可复制的迭代器,也产生可复制的迭代器。因此,重复应用 tee 不会创建新的迭代器层,这是 chain 方法的一个潜在问题。

关于python - 使用 itertools.tee 检查下一个元素时如何最小化空间成本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50599850/

相关文章:

python - Pandas 数据帧 : Can I fetch other column values along with the column on which group by clause has been applied?

python - 如何有效地在迭代器上迭代 "n-wise"

python:切换字典键结构

Powershell:捕获组合输出,仅错误输出,将组合输出发送到控制台

linux - 无法将 "apachectl configtest"的输出记录到文件

python - PyEnchant 在导入时引发 WinError 193,使用 Python 3.3.4

python - 解析可变长度数据

python - BeautifulSoup 每次都有不同的结果

python - itertools 和从分区集中选择

bash - 如何从我的 bash 脚本创建日志文件