2012-06-26 13 views
10

Ich schrieb eine Antwort auf this question, als festgestellt wurde, dass meine einfache Implementierung keine korrekten Ergebnisse lieferte. Während die Fehler der Jagd nach, bemerkte ich folgendes:Warum löscht zip() die Werte meines Generators?

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

Aus irgendeinem Grund gen ‚s next() Methode ein additioinal Mal aufgerufen wird. Um dies zu veranschaulichen, habe ich die folgenden:

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

Antwort

17

Dies geschieht, weil zip Iteratoren from left to right bewertet, was bedeutet, dass nach drei Schritten, ruft sie next() auf gen und erst dann auf iter(range(3)) (oder so ähnlich) und Begegnungen a StopIteration. Um dies zu umgehen, verwenden Sie die kürzere (finite) iterable als das am weitesten links Argument:

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

Your self-answer ist genau richtig, und stellt eine sehr gute Lösung - wenn eines des Arguments zu zip ist immer kürzer als die andere. In Situationen, in denen Sie nicht wissen, welche kürzer sind, finden Sie möglicherweise islice nützlich. islice bietet auch eine einfache Problemumgehung, wenn Sie wollen, dass das erste Element in Ihren Tupeln von Ihrem Generator kommt. In Ihrem Fall könnten Sie dies tun:

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

Ihre Antwort ist wahrscheinlich besser, in diesem Fall - es ist sicherlich einfacher - aber ich dachte, dass ich dies als Ergänzung hinzufügen würde.

Verwandte Themen