Python-Mehrfachzuordnungsanweisungen in einer Zeile
(Keine Sorge, dies ist nicht eine andere Frage über das Auspacken von Tupeln.)
In python eine Anweisung wie foo = bar = baz = 5
weist der Variablen foo, bar, baz und 5. Es weist diese Variablen von Links nach rechts, wie kann bewiesen werden, indem schlimmere Beispiele wie
>>> foo[0] = foo = [0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined
>>> foo = foo[0] = [0]
>>> foo
[[...]]
>>> foo[0]
[[...]]
>>> foo is foo[0]
True
Aber die python language reference besagt, dass Zuweisungsanweisungen haben die form
(target_list "=")+ (expression_list | yield_expression)
und im Auftrag der expression_list
wird zuerst ausgewertet und dann das zuweisen geschieht.
Also, wie kann die Linie foo = bar = 5
gültig ist, gegeben, dass bar = 5
ist nicht ein expression_list
? Wie sind diese mehrere Zuweisungen in einer Zeile immer analysiert und ausgewertet? Lese ich das Referenzhandbuch falsch?
InformationsquelleAutor der Frage mwcvitkovic | 2015-08-22
Du musst angemeldet sein, um einen Kommentar abzugeben.
Alle Kredit geht an @MarkDickinson, wer beantwortet diese in einem Kommentar:
Alle
target_list
Produktionen (also Dinge, die Aussehen wiefoo =
) in einer Zuweisungsanweisung zugewiesen bekommen, von Links nach rechts, um dieexpression_list
auf der rechten Ende der Anweisung, nach derexpression_list
wird ausgewertet.Und natürlich das übliche "Tupel-Auspacken" Zuordnung syntax funktioniert innerhalb dieser syntax, lassen Sie Dinge tun, wie
InformationsquelleAutor der Antwort mwcvitkovic
Mark Dickinson erklärt die syntax von dem, was passiert ist, aber die seltsame Beispiele, die
foo
zeigen, dass die Semantik kann counter-intuitive.In C,
=
ist ein rechts-assoziativer operator liefert als Wert die Rechte Seite der Zuweisung, damit, wenn Sie schreibenx = y = 5
y=5
wird zuerst ausgewertet (zuweisen von 5 bisy
im Prozess) und diesem Wert (5) ist dann zugeordnetx
.Bevor ich das Lesen Frage ich naiv davon ausgegangen, dass etwa die gleiche Sache geschieht in Python. Aber in Python
=
nicht einem Ausdruck (zum Beispiel2 + (x = 5)
ist ein syntax-Fehler). Also Python erreichen müssen mehrere Aufträge in einer anderen Art und Weise.Können wir zerlegen eher als Vermutung:
Sehen diese für eine Beschreibung der byte-code-Anweisungen.
Die erste Anweisung schiebt 5 auf den stack.
Die zweite Instruktion von Duplikaten -- so, jetzt oben auf dem stack hat zwei 5s
STORE_NAME(name)
"Implements name = "TOS", nach der byte-code-DokumentationDamit
STORE_Name(x)
implementiertx = 5
(die 5 oben auf dem Stapel), knallen, 5 aus dem Stapel, wie es geht, nach denenSTORE_Name(y)
implementierty = 5
mit den anderen 5 auf den stack.Den rest der bytecode nicht direkt relevant ist hier.
Im Fall von
foo = foo[0] = [0]
den byte-code ist komplizierter, da der Listen, hat aber eine grundsätzlich ähnliche Struktur. Die wichtige Beobachtung ist, dass, sobald die Liste[0]
ist, erstellt und auf den stack gelegt und dann die AnweisungDUP_TOP
nicht statt anderen kopieren von[0]
auf dem stack, sondern es stellt ein weiteres Referenz auf der Liste. In anderen Worten, zu diesem Zeitpunkt die obersten zwei Elemente des Stacks sind Aliase für die gleiche Liste. Dies zeigt sich besonders deutlich in den etwas einfacheren Fall:Wenn
foo = foo[0] = [0]
ausgeführt wird, wird die Liste[0]
ist erstmals zugewiesenfoo
und dann ein alias der gleichen Liste zugeordnet istfoo[0]
. Dies ist der Grund, warum es die Ergebnisse infoo
ein Zirkelbezug.InformationsquelleAutor der Antwort John Coleman
bar = 5
ist kein Ausdruck. Die mehrfache Zuordnung ist eine separate Anweisung aus der Zuordnung Anweisung; der Ausdruck ist alles, was rechts von der am weitesten rechts=
.Einem guten Weg, daran zu denken, dass die meisten der rechten
=
ist der große separator; alles, was rechts von ihm passiert, von Links nach rechts, und alles, was Links von ihm geschieht, von Links nach rechts.InformationsquelleAutor der Antwort Patrick Maupin
https://docs.python.org/3/reference/simple_stmts.html#grammar-token-assignment_stmt
InformationsquelleAutor der Antwort Veedrac