10

私の単純な実装では正しい結果が得られないことに気付いたとき、私はこの質問への回答を書いていました。バグを探しているときに、次のことに気付きました。

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()メソッドが 1 回追加で呼び出されます。これを説明するために、以下を使用しました。

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

2 に答える 2

17

これは、 がzipイテレータを left から rightに評価するために発生します。つまり、3 つのステップの後、next()ongenを呼び出してから on iter(range(3))(またはそのようなもの) を呼び出し、StopIteration. これを回避するには、より短い (有限の) iterable を左端の引数として使用します。

In [8]: zip(range(3), gen)
0
1
2
Out[8]: [(0, 0), (1, 1), (2, 2)]
于 2012-06-26T15:04:56.393 に答える
7

あなたの自己回答は正確であり、非常に優れた解決策を提示します-引数の1つが常に他の引数よりも短い場合。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)]

この場合、おそらくあなたの答えの方が優れています-確かに簡単です-しかし、補足としてこれを追加すると思いました。

于 2012-06-26T15:51:23.383 に答える