Python: eine Iteration über eine nicht-leere Liste mit nicht if-Klausel kommt leer. Warum?
-
22-08-2019 - |
Frage
Wie kann ein Iterator über eine nicht leere Sequenz, ohne Filterung und keine Aggregation (sum()
, etc.), ergibt nichts?
Betrachten wir ein einfaches Beispiel:
sequence = ['a', 'b', 'c']
list((el, ord(el)) for el in sequence)
Dies ergibt [('a', 97), ('b', 98), ('c', 99)]
wie erwartet.
Nun tauschen nur die ord(el)
für einen Ausdruck aus, der aus irgendeinem Generator (...).next()
mit dem ersten Wert annimmt - vergeben das erfundene Beispiel:
def odd_integers_up_to_length(str):
return (x for x in xrange(len(str)) if x%2==1)
list((el, odd_integers_up_to_length(el).next()) for el in sequence)
Dies ergibt []
. Ja, leere Liste. Keine ('a',
stuff)
Tupel. Nichts.
Aber wir sind nicht Filterung oder Aggregation oder verringert wird. Ein Generator Ausdruck über n
Objekte ohne Filterung oder Aggregation müssen n
Objekte ergeben, nicht wahr? Was ist los?
Lösung
odd_integers_up_to_length(el).next()
erhöhen wird StopIteration, die nicht dort gefangen wird, ist aber für den Generator Ausdruck in ihr gefangen, es zu stoppen, ohne jemals etwas nachgebend.
Blick auf der ersten Iteration, wenn der Wert 'a':
>>> odd_integers_up_to_length('a').next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Andere Tipps
Was passiert, ist, dass der next()
Aufruf eine StopIteration
Ausnahme auslöst, die den Stapel an den äußeren Generator Ausdruck Blasen nach oben und stoppen , die Iteration.
Ein StopIteration
ist der normale Weg für ein Iterator zu signalisieren, dass es gemacht wird. Im Allgemeinen wir sehen es nicht, weil in der Regel der next()
Anruf innerhalb eines Konstrukts auftritt, die den Iterator verbraucht, z.B. for x in iterator
oder sum(iterator)
. Aber wenn wir next()
direkt anrufen, sind wir es, die verantwortlich für die StopIteration
zu kontrollieren. Nicht dabei ein Leck in dem Abstraktion Federn, die hier zu unerwartetem Verhalten führt in der äußeren Iteration.
Die Lektion, nehme ich an: über direkte Aufrufe next()
vorsichtig sein
str ein reserviertes Schlüsselwort ist, sollten Sie Ihre Variablennamen anders
Ich war auch über die nächste
beraten>>> seq=['a','b','c']
>>> list((el,4) for el in seq)
[('a',4), ('b',4), ('c',4)]
So ist es nicht list
Sie Probleme geben hier ...