itertools.tee是如何工作的,能否复制'itertools.tee'以保存其“状态”?

9 投票
1 回答
11863 浏览
提问于 2025-04-16 05:40

下面是一些关于 itertools.tee 的测试:

    li = [x for x in range(10)]
    ite = iter(li)
==================================================
    it = itertools.tee(ite, 5)
    >>> type(ite)
    <type 'listiterator'>
    >>> type(it)
    <type 'tuple'>
    >>> type(it[0])
    <type 'itertools.tee'>
    >>> 

    >>> list(ite)
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> list(it[0])          # here I got nothing after 'list(ite)', why?
    []
    >>> list(it[1])
    []
====================play again===================
    >>> ite = iter(li)
    it = itertools.tee(ite, 5)
    >>> list(it[1])
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> list(it[2])
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> list(it[3])
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> list(it[4])
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> list(ite)
    []                       # why I got nothing? and why below line still have the data?   
    >>> list(it[0])
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> list(it[0])
    []
====================play again===================    
    >>> ite = iter(li)
    itt = itertools.tee(it[0], 5)    # tee the iter's tee[0].
    >>> list(itt[0])
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> list(itt[1])
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> list(it[0])
    []                               # why this has no data?
    >>> list(it[1])
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> list(ite)
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]  

我有几个问题:

  1. tee 是怎么工作的?为什么有时候原始的迭代器“有数据”,而有时候又没有?
  2. 我可以保持一个迭代器的深拷贝作为“状态种子”,以保持原始迭代器的状态,然后再用 tee 吗?
  3. 我可以交换两个迭代器或者两个 itertools.tee 吗?

谢谢!

1 个回答

16

tee 是一个工具,它会接管原来的迭代器;一旦你使用了 tee,就应该放弃原来的迭代器,因为 tee 会控制它(除非你真的很清楚自己在做什么)。

你可以用 copy 模块来复制一个 tee:

import copy, itertools
it = [1,2,3,4]
a, b = itertools.tee(it)
c = copy.copy(a)

... 或者通过调用 a.__copy__() 来实现。

要注意的是,tee 是通过记录从原始迭代器中读取的所有值来工作的,这些值可能仍然会被复制的迭代器使用。

举个例子,

a = [1,2,3,4]
b, c = itertools.tee(a)
next(b)

此时,bc 下面的 tee 对象已经读取了一个值,1。它把这个值存储在内存中,因为它需要记住这个值,以便在迭代 c 时使用。它必须在所有复制的 tee 被消费之前,保持每个值在内存中。

这样做的后果是,你在复制 tee 时需要小心“保存状态”。如果你没有从“保存状态”的 tee 中实际消费任何值,tee 会一直把迭代器返回的每个值都保存在内存中,直到这个复制的 tee 被丢弃并被垃圾回收。

撰写回答