[英]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)]
无论出于何种原因, gen
的next()
方法称为一个额外的时间。 为了说明这一点,我使用了以下内容:
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.