Verhalten der exec-Funktion in Python 2 und Python 3
Folgende code gibt unterschiedliche Ausgabe in Python2
und in Python3
:
from sys import version
print(version)
def execute(a, st):
b = 42
exec("b = {}\nprint('b:', b)".format(st))
print(b)
a = 1.
execute(a, "1.E6*a")
Python2
Drucke:
2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)]
('b:', 1000000.0)
1000000.0
Python3
Drucke:
3.2.3 (default, Apr 11 2012, 07:15:24) [MSC v.1500 32 bit (Intel)]
b: 1000000.0
42
Warum Python2
binden die variable b
innerhalb der execute
- Funktion, um die Werte in der Zeichenfolge der exec
Funktion, während Python3
dies nicht tut? Wie kann ich erreichen, das Verhalten von Python2
im Python3
? Ich habe bereits versucht, pass Wörterbücher für globals und locals zu exec
Funktion in Python3
, aber nichts funktionierte bisher.
--- EDIT ---
Nach der Lektüre Martijns Antwort, die ich weiter analysiert und diese mit Python3
. Im folgenden Beispiel gebe ich die locals()
dictionay als d
zu exec
, aber d['b']
druckt etwas anderes, als nur zu drucken b
.
from sys import version
print(version)
def execute(a, st):
b = 42
d = locals()
exec("b = {}\nprint('b:', b)".format(st), globals(), d)
print(b) # This prints 42
print(d['b']) # This prints 1000000.0
print(id(d) == id(locals())) # This prints True
a = 1.
execute(a, "1.E6*a")
3.2.3 (default, Apr 11 2012, 07:15:24) [MSC v.1500 32 bit (Intel)]
b: 1000000.0
42
1000000.0
True
Den Vergleich mit den ids d
und locals()
zeigt, dass Sie das gleiche Objekt. Aber unter diesen Bedingungen b
sollten die gleichen sein, wie d['b']
. Was ist falsch in meinem Beispiel?
print
ist eine Anweisung in Python 2Aber das ist nicht die Frage hier. Aber so ist
exec
, btw.Aber in 2.7.2
exec
als eine Funktion scheint zu funktionieren. Mittlerweile habe ich heraus gefunden, dass ich verwenden können eval
zu gewinnen, das Ergebnis will ich nicht. Aber die Frage bleibt die gleiche. Ich habe auch versucht, diese außerhalb einer Funktion nennen. Dann beide Versionen das gleiche zu tun.denn die Art und Weise Sie es verwenden, die Klammer nur die Gruppe der Meinungsäußerung, was bedeutet, dass in python 2 Sie sind der ignoriert.
Das würde bedeuten, dass
b
bleibt die gleiche, in Python2
, richtig? Aber es änderte sich mit der exec
- Anweisung oder Funktion in Python2
und nicht in Python3
.InformationsquelleAutor Holger | 2013-02-26
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gibt es einen großen Unterschied zwischen
exec
in Python 2 undexec()
in Python 3. Sie behandelnexec
als eine Funktion, aber es ist wirklich ein Anweisung in Python 2.Weil dieser Differenz, die Sie nicht ändern können lokale Variablen in der Funktion Umfang in Python 3 mit
exec
, obwohl es möglich war, in Python 2. Auch nicht deklarierte Variablen.locals()
spiegelt lediglich die lokalen Variablen in eine Richtung. Die folgenden noch nie gearbeitet, in entweder 2 oder 3:In Python 2, mit der
exec
Aussage gemeint ist der compiler wusste, dass Sie das ausschalten der local-Bereich-Optimierungen (Wechsel vonLOAD_FAST
zuLOAD_NAME
zum Beispiel, zu suchen Variablen in lokale und Globale Bereiche). Mitexec()
ist eine Funktion, die option ist nicht mehr verfügbar und die Funktion scopes sind jetzt immer optimiert.Darüber hinaus in Python 2 die
exec
Anweisung explizit kopiert alle Variablen gefunden, die inlocals()
zurück, um die Funktion einheimischen mitPyFrame_LocalsToFast
, aber nur, wenn kein globals und einheimischen Parameter geliefert wurden.Die richtige work-around ist, verwenden Sie einen neuen namespace (ein Wörterbuch) für Ihre
exec()
nennen:Den
exec()
- Dokumentation ist sehr explizit über diese Einschränkung:Ah, mein Fehler, drehen wir diese um.
Ich bekommen es in das Ende. Ich habe deine Frage falsch verstanden, ich dachte, Sie wollten, dass die Python-3 Verhalten in Python 2 statt. Ich war ein wenig zu sicher, was Sie gesucht haben. 🙂
Hallo Martijn, ich will es so wie es ist in
Python2
. Daherb
sollte 1000000.0 danach. Siehe mein edit in der Frage. Ich habe keine Erklärung für dieses Verhalten.Endgültige, abschließende Antwort. Sie kann es nicht. Ich entschuldige mich für die nicht mehr rigoros in meiner Prüfung und das Verständnis. Python 3 geschlossene Tür oder ändern von lokalen Variablen in der Funktion Umfang.
InformationsquelleAutor Martijn Pieters
Ich würde sagen, es ist ein Fehler von Python ist3.
Drucke "2".
Drucke "2".
Aber
schlägt mit
--- EDIT ---
Ein weiteres Interessantes Verhalten:
Ausgänge
Und auch
Ausgänge
Offenbar, die Aktion von
exec
auf die einheimischen, ist die folgende:exec
und diese variable eine lokale variable, dannexec
ändert die internen Wörterbuch (der zurückgegebenenlocals()
) und nicht wieder in den ursprünglichen Zustand. Ein Aufruflocals()
Aktualisierungen dem Wörterbuch (wie beschrieben in Abschnitt 2 der python-Dokumentation), und die Werte innerhalbexec
vergessen.Die Notwendigkeit der Berufung
locals()
zu aktualisieren das Wörterbuch ist nicht ein Fehler von Python ist3, weil es dokumentiert ist, aber es ist nicht intuitiv. Darüber hinaus ist die Tatsache, dass änderungen von einheimischen innerhalbexec
sich nicht ändern, die einheimischen von der Funktion ist eine dokumentierte Unterschied mit python2 (die Dokumentation sagt "Pass eine explizite einheimischen Wörterbuch, wenn Sie brauchen, um zu finden Sie unter Auswirkungen des Kodex auf die einheimischen nach der Funktion exec() kehrt zurück"), und ich bevorzuge das Verhalten von python2.exec
und diese variable nicht existiert, dannexec
ändert die internen Wörterbuch, es sei denn, die variable ist gesetzt, danach. Es scheint, dass es einen Fehler in der Art und Weiselocals()
Aktualisierungen dem Wörterbuch ; dieser bug ermöglicht Zugriff auf den Wert gesetzt, innerhalbexec
durch den Aufruflocals()
nachexec
.Dies scheint nur eine Optimierung detail.
locals()
gibt ein veränderliches Objekt-Referenzen auf alle lokalen Variablen.locals()
immer gibt das gleiche Objekt zurück, unabhängig davon, wie oft Sie es nennen. Scheinbar das gleiche Objekt verwendet wird, innerhalbexec()
daherl
bezieht sich auf das gleiche Objekt, dasexec
verwendet, so sieht es die änderungen. Jedoch, nach dem Aufruflocals()
wieder, die (veränderliche) - Objekt aktualisiert wird. Daherl
noch Punkte die gleichen, die jetzt aktualisierte Objekt. Versuchen Sie es selbst:def u(): l=locals(); print(l); a=1; print(l); print(locals()); print(l)
. Gut zu finden, BTW 😉InformationsquelleAutor LRGH
Um es zusammenzufassen:
exec
stammt ausexec
wird eine Anweisung in Python 2, und es wurde eine Funktion in Python 3.Der einzige Unterschied zwischen Python 2 und Python 3 ist, dass, ja,
exec
ist in der Lage, ändern Sie den lokalen Gültigkeitsbereich der umgebenden Funktion, die in Python 2 (denn es ist eine Aussage und kann den Zugriff auf die aktuellen lokalen Bereich) und diese nicht mehr in Python 3 (weil es jetzt eine Funktion, so läuft in seinem eigenen lokalen Bereich).Die Reizung, aber hat nichts zu tun mit der
exec
Anweisung, es nur rührt von einem speziellen Verhalten detail:locals()
gibt etwas, das ich nennen will "eine Umfang-Weise veränderlich singleton, die nach dem Aufruflocals()
immer nur Verweise, die alle Variablen im lokalen Bereich".Bitte beachten Sie, dass das Verhalten von
locals()
änderte sich nicht zwischen Python 2 und 3. So, dieses Verhalten zusammen mit ändern, wieexec
Werke sieht wie unberechenbar, aber nicht, wie Sie es nur macht, einige Details, die immer da war.Was bedeutet "ein Umfang-Weise veränderlich singleton Referenzen auf Variablen im lokalen Bereich"?
scope-wise singleton
, wie unabhängig davon, wie oft Sie anrufenlocals()
im gleichen Umfang, ist das zurückgegebene Objekt ist immer das gleiche.id(d) == id(locals())
, weild
undlocals()
beziehen sich auf das gleiche Objekt, die gleiche singleton, so kann es nur einen (in einem anderen Bereich erhalten Sie ein anderes Objekt, aber in den gleichen Bereich, den Sie sehen nur das einzelne).mutable
, als es ein normales Objekt, so können Sie es ändern.locals()
zwingt alle Einträge im Objekt der Referenz der Variablen im lokalen Bereich wieder.d
), dadurch verändert sich das Objekt, es ist ein normaler veränderliches Objekt.Diese änderungen der singleton nicht ausbreiten zurück in den lokalen Bereich, da alle Eingaben in das Objekt
references to the variables in the local scope
. Also, wenn Sie ändern die Einträge, diese änderungen der singleton-Objekt, und nicht den Inhalt, wo "die Verweise darauf hingewiesen, bevor Sie ändern Sie den Verweis" (daher ändern Sie nicht die lokalen Variablen).In Python Zeichenketten und Zahlen sind nicht veränderbar. Das heißt, Sie weisen etwas auf einen Eintrag, ändern Sie nicht das Objekt, in dem die Einstiegspunkte, Sie führen ein neues Objekt und eine Referenz zuweisen, die auf den Eintrag. Beispiel:
Neben der Optimierung bedeutet dies:
LOCALS['a']
(wo
LOCALS
werden die internen lokalen Bereich)SINGLETON
ObjektSINGLETON
, so verweisen alle Einträge inLOCALS
SINGLETON
inLOCALS['d']
d['a']
SINGLETON
ist ebenfalls aktualisiert.LOCALS
ist nicht aktualisiert,also die lokale variable
a
oderLOCALS['a']
noch ist die Nummer(1)locals()
erneut aufgerufen wird, dieSINGLETON
aktualisiert.d
bezieht sich aufSINGLETON
, nichtLOCALS
,d
änderungen, auch!Fazit:
Können Sie nicht zurück zu bringen die
exec
Verhalten von Python 2 zu Python 3 (außer durch änderung des Codes), da es keine Möglichkeit gibt, das zu ändern und den lokalen Variablen, die außerhalb des Programms fließen nicht mehr.Jedoch können Sie bringen das Verhalten von Python 3 auf Python 2, so dass Sie, heute können Programme schreiben, die die gleiche, unabhängig davon, ob Sie laufen mit Python 3 und Python 2. Dies ist, weil in (neueren) Python 2 können Sie
exec
mit Funktion wie Argumente als gut (in der Tat, jene ist ein 2 - oder 3-Tupel), ermöglicht die Verwendung der gleichen syntax bei gleicher Semantik, bekannt aus Python 3:(das funktioniert nur in Python 2) wird zu (für Python 2 und 3):
Aber Vorsicht, daß
"code"
kann nicht mehr alter die lokale einschließenden Geltungsbereich diese Weise. Siehe auch https://docs.python.org/2/reference/simple_stmts.html#execEinige Letzte Worte:
Die änderung der
exec
in Python 3 ist gut. Aufgrund der Optimierung.In Python 2 Sie waren nicht in der Lage zu optimieren, über
exec
, weil der Staat alle lokalen Variablen, die enthalten unveränderliche Inhalte könnten unvorhersehbar ändern. Dies kann nicht mehr passieren. Nun die üblichen Regeln der Funktionsaufrufe anwenden zuexec()
wie alle anderen Funktionen auch.InformationsquelleAutor Tino
Ich fürchte, ich kann nicht erklären, was es genau ist, aber es geht im Grunde aus der Tatsache, dass b innerhalb der Funktion lokal ist, und
exec()
scheint, weisen die globalen b. Sie müssen erklären b global innerhalb der Funktion und innerhalb der exec-Anweisung.Versuchen Sie dies:
Gibt mir
Können Sie sehen, dass außerhalb der Funktion, die Globale b ist automatisch abgeholt. Innerhalb der Funktion, die Sie drucken wollen, die lokale b.
Hinweis, ich hätte gedacht, dass
exec()
immer verwendet das Globale b zuerst, so dass inexecute2()
Sie brauchen nicht zu erklären, es in derexec()
Funktion. Aber ich finde das nicht funktioniert (das ist der Teil, den ich nicht genau beschreiben kann).locals()
statt.Die OP ist auf der Suche zu modifizieren einheimischen statt, nicht globals. Ihre interpretation ist, fürchte ich, falsch, noch ist Ihre Lösung.
InformationsquelleAutor