【问题标题】:Why does zip() drop the values of my generator?为什么 zip() 会删除我的生成器的值?
【发布时间】:2012-06-26 15:04:55
【问题描述】:

当我注意到我的简单实现没有产生正确的结果时,我正在给this question 写一个答案。在寻找错误时,我注意到以下内容:

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)]

【问题讨论】:

    标签: python


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      Your self-answer 完全正确,并且提供了一个非常好的解决方案——if 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)]
      

      在这种情况下,您的答案可能会更好——它肯定更简单——但我想我会添加这个作为补充。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-04-16
        • 1970-01-01
        • 2018-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-10
        相关资源
        最近更新 更多