Python itertools tee,克隆和缓存

时间:2013-11-20 03:20:03

标签: python itertools

假设:使用python itertools.tee()时,所有重复的迭代器都会引用原始迭代器,并且缓存原始迭代器以提高性能。

我在以下调查中主要关注的是预期/正确的缓存行为的我的IDEA。
编辑:我对正确缓存的想法是基于有缺陷的功能假设。最终需要一个围绕tee的小包装(这可能会对缓存产生影响)。


问题:

假设我使用tee:a, b, c = itertools.tee(myiter,3)创建3个迭代器克隆。还假设在这一点上,我删除了对原始myiter的所有引用(意思是,我的代码没有很好的方式可以在下文中引用原始代码)。

在代码的某个稍后部分,如果我决定要另一个myiter的克隆,我可以重新发布()我的一个副本吗? (正确缓存回原始缓存的myiter

换句话说,在稍后的某个时刻,我希望我反而使用了这个: a, b, c, d = itertools.tee(myiter,4)。 但是,由于我已经放弃了对原始myiter的所有引用,我能够集中考虑的最好方法是: copytee = itertools.tee(a, 1) #where 'a' is from a previous tee()

tee()知道我想要什么吗? (我真的想要创建一个基于原始myiter的克隆,而不是中间克隆a(可能会被部分消费))

1 个答案:

答案 0 :(得分:6)

tee没有什么神奇之处。它只是聪明;-)在任何点,tee克隆传递给它的迭代器。这意味着克隆的迭代器将从上的这一点产生由传入的迭代器产生的值。但是,在调用 tee之前,他们不可能重现

让我们用比你的例子简单得多的东西来展示它:

>>> it = iter(range(5))
>>> next(it)
0

0现在已经消失了 - 永远。 tee()无法取回它:

>>> a, b = tee(it)
>>> next(a)
1

所以a推动it生成下一个值。这是缓存的值,因此其他克隆也可以重现它:

>>> next(b)
1

要获得该结果,未触及it - 从内部缓存中检索到1。现在所有itab都产生了1,1也永远消失了。

我不知道这是否能回答你的问题 - 回答“tee()知道我想要什么吗?”似乎需要心灵感应;-)也就是说,我不知道你的意思是“适当的缓存”。如果您提供了您希望的输入/输出行为的确切示例,那将是最有帮助的。

除此之外,Python文档提供的Python代码相当于tee(),也许正在研究可以回答你的问题:

def tee(iterable, n=2):
    it = iter(iterable)
    deques = [collections.deque() for i in range(n)]
    def gen(mydeque):
        while True:
            if not mydeque:             # when the local deque is empty
                newval = next(it)       # fetch a new value and
                for d in deques:        # load it to all the deques
                    d.append(newval)
            yield mydeque.popleft()
    return tuple(gen(d) for d in deques)

从中可以看出,例如,没有关于迭代器内部状态的任何内容被缓存 - 所有缓存的是由传入的迭代器生成的值,从时间{{1开始}} 叫做。每个克隆都有自己的tee()(FIFO列表)到目前为止生成的传入迭代器的值,并且所有克隆都知道传入的迭代器。所以对于你真正希望的任何事情来说,这可能太简单了。