Gegeben folgenden Code:
def A() :
b = 1
def B() :
# I can access 'b' from here.
print( b )
# But can i modify 'b' here? 'global' and assignment will not work.
B()
A()
Denn der Code in der B()
Funktionsvariablen b
befindet sich im äußeren Bereich, jedoch nicht im globalen Bereich. Ist es möglich, b
Variablen innerhalb der B()
Funktion zu ändern ? Sicher kann ich es von hier aus lesen und print()
, aber wie kann ich es ändern?
python
python-2.7
grigoryvp
quelle
quelle
b
veränderlich ist. Eine Zuweisung anb
maskiert den äußeren Bereich.nonlocal
die nicht auf 2.x zurückportiert wurde. Es ist ein wesentlicher Bestandteil der Schließungsunterstützung.Antworten:
Python 3.x hat das
nonlocal
Schlüsselwort . Ich denke, das macht, was Sie wollen, aber ich bin nicht sicher, ob Sie Python 2 oder 3 ausführen.Für Python 2 verwende ich normalerweise nur ein veränderbares Objekt (wie eine Liste oder ein Diktat) und mutiere den Wert, anstatt ihn neu zuzuweisen.
Beispiel:
Ausgänge:
quelle
class nonlocal: pass
im äußeren Bereich. Dannnonlocal.x
kann im inneren Bereich zugewiesen werden.SyntaxError
. VielleichtNonLocal
?Nonlocal
? :-)Sie können eine leere Klasse verwenden, um einen temporären Bereich zu speichern. Es ist wie das Veränderliche, aber etwas hübscher.
Dies ergibt die folgende interaktive Ausgabe:
quelle
Ich bin ein bisschen neu in Python, aber ich habe ein bisschen darüber gelesen. Ich glaube, das Beste, was Sie bekommen werden, ähnelt der Java-Problemumgehung, bei der Ihre äußere Variable in eine Liste eingeschlossen wird.
Bearbeiten: Ich denke, dies war wahrscheinlich vor Python 3 wahr. Sieht aus wie
nonlocal
ist Ihre Antwort.quelle
Nein, das kannst du zumindest auf diese Weise nicht.
Weil die "Set-Operation" im aktuellen Bereich einen neuen Namen erstellt, der den äußeren abdeckt.
quelle
Für alle, die dies viel später betrachten, ist eine sicherere, aber schwerere Problemumgehung. Ohne dass Variablen als Parameter übergeben werden müssen.
quelle
Die kurze Antwort, die nur automatisch funktioniert
Ich habe eine Python-Bibliothek erstellt, um dieses spezielle Problem zu lösen. Es wird unter der Unlisence veröffentlicht, verwenden Sie es also, wie Sie möchten. Sie können es mit https://github.com/hirsimaki-markus/SEAPIE installieren
pip install seapie
oder die Homepage hier besuchenuser@pc:home$ pip install seapie
Ausgänge
Die Argumente haben folgende Bedeutung:
B()
, 1 bedeutet ElternA()
und 2 würde Großeltern<module>
alias global bedeutenDie lange Antwort
Das ist komplizierter. Seapie bearbeitet die Frames im Call Stack mit CPython API. CPython ist der De-facto-Standard, sodass sich die meisten Menschen keine Sorgen machen müssen.
Die magischen Wörter, an denen Sie wahrscheinlich interessiert sind, wenn Sie dies lesen, sind die folgenden:
Letzteres erzwingt, dass Aktualisierungen in den lokalen Bereich übertragen werden. Lokale Bereiche werden jedoch anders als der globale Bereich optimiert, sodass die Einführung neuer Objekte einige Probleme verursacht, wenn Sie versuchen, sie direkt aufzurufen, wenn sie in keiner Weise initialisiert werden. Ich werde einige Möglichkeiten kopieren, um diese Probleme von der Github-Seite zu umgehen
Wenn Sie der
exec()
Meinung sind, dass die Verwendung nicht das ist, mit dem Sie arbeiten möchten, können Sie das Verhalten emulieren, indem Sie das wahre lokale Wörterbuch aktualisieren (nicht das von local () zurückgegebene). Ich werde ein Beispiel von https://faster-cpython.readthedocs.io/mutable.html kopierenAusgabe:
quelle
Ich denke nicht, dass du das machen willst. Funktionen, die Dinge in ihrem umschließenden Kontext verändern können, sind gefährlich, da dieser Kontext ohne Kenntnis der Funktion geschrieben werden kann.
Sie können es explizit machen, indem Sie entweder B zu einer öffentlichen Methode und C zu einer privaten Methode in einer Klasse machen (wahrscheinlich der beste Weg). oder indem Sie einen veränderlichen Typ wie eine Liste verwenden und diese explizit an C übergeben:
quelle
nonlocal
Schlüsselwort - aber es liegt an Ihnen, es mit großer Vorsicht zu verwenden.Sie können, aber Sie müssen die globale Anweisung verwenden (keine wirklich gute Lösung wie immer, wenn Sie globale Variablen verwenden, aber es funktioniert):
quelle
Ich weiß nicht, ob es ein Attribut einer Funktion gibt, das
__dict__
den Außenraum der Funktion angibt, wenn dieser Außenraum nicht der globale Raum ist == das Modul, was der Fall ist, wenn die Funktion eine verschachtelte Funktion ist. in Python 3.Aber in Python 2 gibt es meines Wissens kein solches Attribut.
Die einzigen Möglichkeiten, das zu tun, was Sie wollen, sind:
1) Verwenden eines veränderlichen Objekts, wie von anderen gesagt
2)
Ergebnis
.
Kein
Die Lösung von Cédric Julien hat einen Nachteil:
Ergebnis
Das globale b nach der Ausführung von
A()
wurde geändert und kann möglicherweise nicht gewünscht werdenDies ist nur dann der Fall, wenn sich im globalen Namespace ein Objekt mit der Kennung b befindet
quelle