繁体   English   中英

为什么zip()会丢弃我的生成器的值?

[英]Why does zip() drop the values of my generator?

当我注意到我的简单实现没有产生正确的结果时,我正在写这个问题的答案。 在追捕这个bug时,我注意到以下内容:

In [1]: import itertools
In [2]: gen = itertools.cycle((0,1,2))

In [3]: zip(gen, range(3))
Out[3]: [(0, 0), (1, 1), (2, 2)]

In [4]: zip(gen, range(3))
Out[4]: [(1, 0), (2, 1), (0, 2)]

无论出于何种原因, gennext()方法称为一个额外的时间。 为了说明这一点,我使用了以下内容:

class loudCycle(itertools.cycle):
    def next(self):
        n = super(loudCycle, self).next()
        print n
        return n

In [6]: gen = loudCycle((0,1,2))
In [7]: zip(gen, range(3))
0
1
2
0
Out[7]: [(0, 0), (1, 1), (2, 2)]

发生这种情况是因为zip 从左到右评估迭代器,这意味着,在三个步骤之后,它在gen上调用next() ,然后在iter(range(3)) (或类似的东西next()上调用并遇到StopIteration 要解决这个问题,请使用较短的(有限)迭代作为最左边的参数:

In [8]: zip(range(3), gen)
0
1
2
Out[8]: [(0, 0), (1, 1), (2, 2)]

你的自我答案是完全正确的,并提出了一个非常好的解决方案 - 如果 zip一个参数总是比另一个短。 但是,在您不知道哪个更短的情况下,您可能会发现islice很有用。 如果您希望元组中的第一项来自您的生成器, islice还提供了一种简单的解决方法。 在您的情况下,您可以这样做:

>>> import itertools
>>> gen = itertools.cycle(('a', 'b', 'c'))
>>> seq = range(3)
>>> zip(itertools.islice(gen, len(seq)), seq)
[('a', 0), ('b', 1), ('c', 2)]
>>> zip(itertools.islice(gen, len(seq)), seq)
[('a', 0), ('b', 1), ('c', 2)]

在这种情况下你的答案可能更好 - 它当然更简单 - 但我想我会补充这个。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM