die Ausbeute in der Liste Verstehens-und generator-Ausdrücke
Folgendes Verhalten erscheint eher kontraintuitiv für mich (Python 3.4):
>>> [(yield i) for i in range(3)]
<generator object <listcomp> at 0x0245C148>
>>> list([(yield i) for i in range(3)])
[0, 1, 2]
>>> list((yield i) for i in range(3))
[0, None, 1, None, 2, None]
Die Zwischenwerte der letzten Zeile sind tatsächlich nicht immer None
Sie sind, was wir send
in den generator, vergleichbar (denke ich mal) an den folgenden generator:
def f():
for i in range(3):
yield (yield i)
Scheint es mir komisch, dass Sie diese drei Zeilen, alle am arbeiten. Die Referenz sagt, dass yield
ist nur erlaubt in einer Funktion, definition (obwohl ich vielleicht liest es falsch und/oder kann es einfach nur kopiert worden sind, die von der älteren version). Die ersten beiden Zeilen erzeugen ein SyntaxError
in Python 2.7, aber die Dritte Zeile nicht.
Auch, es scheint seltsam
- dass eine list comprehension gibt einen generator und nicht eine Liste
- und dass der generator expression umgewandelt, um eine Liste und die entsprechende list comprehension unterschiedliche Werte enthalten.
Könnte jemand mehr Informationen liefern?
InformationsquelleAutor zabolekar | 2015-08-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Generator-Ausdrücke, und set und dict Verstehens kompiliert werden (generator) von function-Objekten. In Python 3, Liste Verstehens dieselbe Behandlung bekommen; Sie sind alle, im wesentlichen, eine neue nested scope.
Können Sie sehen, wenn Sie versuchen, zu zerlegen, ein generator-Ausdruck:
Oben zeigt, dass ein generator-Ausdruck wird kompiliert, um ein code-Objekt geladen, wie eine Funktion (
MAKE_FUNCTION
erstellt die Funktion Objekt aus der Objekt-code). Die.co_consts[0]
Referenz können wir sehen, das code-Objekt erzeugt für den Ausdruck, und es verwendetYIELD_VALUE
nur wie ein generator funktionieren würde.Als solche, die
yield
Ausdruck in diesem Kontext, wie der compiler sieht diese als Funktionen-in-Verkleidung.Dies ist ein Fehler;
yield
hat keinen Platz in diesen Ausdrücken. Die Python Grammatik vor Python 3.7 ermöglicht es (das ist, warum der code ist kompilierbar), aber dieErtrag
- Ausdruck-Spezifikation zeigt, dass die Verwendungyield
hier sollte eigentlich nicht funktionieren:Dieser wurde bestätigt, dass ein bug in Problem 10544. Die Auflösung der Fehler ist, dass mit
yield
undyield from
wird heben Sie einSyntaxError
in Python-3.8; in Python 3.7 es wird eineDeprecationWarning
zu gewährleisten-code nicht mehr mit diesem Konstrukt. Sehen Sie die gleiche Warnung in Python 2.7.15 und wenn Sie verwenden Sie die-3
- Befehl Linie Schalter ermöglicht Python-3-Kompatibilität Warnungen.Den 3.7.0b1 Warnung sieht wie folgt aus; drehen Warnungen in Fehler gibt Ihnen eine
SyntaxError
Ausnahme, wie in 3.8:Die Unterschiede zwischen dem, wie
yield
in einer Liste Verständnis undyield
in einen generator-Ausdruck arbeiten stammen aus den Unterschiede, wie diese beiden Ausdrücke implementiert sind. In Python 3 eine list comprehension verwendetLIST_APPEND
Anrufe hinzufügen, die oben auf dem Stapel in die Liste gebaut wird, während ein generator-Ausdruck stattdessen ergibt diesen Wert. Hinzufügen in(yield <expr>)
fügt nur ein weiteresYIELD_VALUE
opcode:Den
YIELD_VALUE
opcode bei bytecode Indizes 15 und 12, bzw. ist extra, ein Kuckuck im nest. Also für die Liste-das Verständnis-aktiviert-generator Sie haben 1 Ertrag produzieren die Spitze des Stapels zu jeder Zeit (anstelle der oben auf dem Stapel mit denyield
return-Wert), und für den generator-Ausdruck-Variante geben Sie den oben auf dem stack (integer) und dann ergeben wieder, aber jetzt ist der stack enthält den Rückgabewert deryield
und Sie erhaltenNone
das zweite mal.Für die list-comprehension dann, den beabsichtigten
list
Objekt Ausgang ist noch zurückgegeben, aber Python 3 sieht dieser als generator, so ist der Rückgabewert stattdessen angebracht, um dieStopIteration
Ausnahme alsvalue
Attribut:Diese
None
Objekte sind die Rückgabe-Werte aus deryield
Ausdrücken.Und bekräftigt dies nochmals; das gleiche Problem gilt für Wörterbuch-und set-comprehension in Python 2 und Python 3 als auch; in Python 2 die
yield
Rückgabewerte sind noch Hinzugefügt die beabsichtigte Wörterbuch oder set-Objekt, und der Rückgabewert ist 'ergab' last statt befestigt, um dieStopIteration
Ausnahme:yield-atom
ist erlaubt, die innerhalb eines Ausdrucks (innerhalb einer generator-Funktion). Dies könnte noch mehr problematisch, wenn dieyield-atom
ist irgendwie misimplemented.das ist, was ich sage; die Grammatik erlaubt. Der Fehler, den ich finden versucht, mit einem
yield
als Teil einer generator expression innerhalb einer generator-Funktion, wobei die Erwartung ist, dass dieyield
gilt für die generator-Funktion, nicht der generator expression nested scope.Wow. Sehr informativ in der Tat. Also, wenn ich das richtig verstanden habe, passierte Folgendes: eine Funktion, die beides enthält
yield
undreturn
sollte, wie dokumentiert ist, werden Sie eine generator-Funktion, derenreturn
ed Wert muss das Grundstück in derStopIteration
Ausnahme, und der bytecode für eine Liste Verständnis mityield
innen aussieht (obwohl es nicht beabsichtigt war), wie der bytecode für eine solche Funktion.so etwas wie, dass; die Schritte sind so etwas wie: der compiler kommt auf eine Liste Verständnis, so baut ein code-Objekt; der compiler kommt auf einen
yield
Ausdruck, so markiert die aktuelle code-Objekt als generator. Voila, wir haben eine generator-Funktion.2.7 änderungen gibt es bei der Verwendung der
-3
Kompatibilität Warnungen.InformationsquelleAutor Martijn Pieters