In der Python-Dokumentation scheint unklar zu sein, ob Parameter als Referenz oder Wert übergeben werden, und der folgende Code erzeugt den unveränderten Wert 'Original'.
class PassByReference:
def __init__(self):
self.variable = 'Original'
self.change(self.variable)
print(self.variable)
def change(self, var):
var = 'Changed'
Kann ich etwas tun, um die Variable als tatsächliche Referenz zu übergeben?
python
reference
parameter-passing
pass-by-reference
David Sykes
quelle
quelle
Antworten:
Argumente werden durch Zuweisung übergeben . Es gibt zwei Gründe dafür:
Damit:
Wenn Sie ein veränderbares Objekt an eine Methode übergeben, erhält die Methode einen Verweis auf dasselbe Objekt und Sie können es zur Freude Ihres Herzens mutieren. Wenn Sie jedoch den Verweis in der Methode erneut binden, weiß der äußere Bereich nichts darüber und danach Wenn Sie fertig sind, zeigt die äußere Referenz immer noch auf das ursprüngliche Objekt.
Wenn Sie ein unveränderliches Objekt an eine Methode übergeben, können Sie die äußere Referenz immer noch nicht erneut binden und das Objekt nicht einmal mutieren.
Um es noch deutlicher zu machen, lassen Sie uns einige Beispiele nennen.
Liste - ein veränderlicher Typ
Versuchen wir, die Liste zu ändern, die an eine Methode übergeben wurde:
Ausgabe:
Da der übergebene Parameter ein Verweis auf
outer_list
und keine Kopie davon ist, können wir die Methoden der Mutationsliste verwenden, um ihn zu ändern und die Änderungen im äußeren Bereich wiederzugeben.Nun wollen wir sehen, was passiert, wenn wir versuchen, die als Parameter übergebene Referenz zu ändern:
Ausgabe:
Da der
the_list
Parameter als Wert übergeben wurde, hatte das Zuweisen einer neuen Liste keine Auswirkung, die der Code außerhalb der Methode sehen konnte. Dasthe_list
war eine Kopie derouter_list
Referenz, und wir hattenthe_list
auf eine neue Listeouter_list
verwiesen , aber es gab keine Möglichkeit zu ändern, wo darauf hingewiesen wurde.String - ein unveränderlicher Typ
Es ist unveränderlich, daher können wir nichts tun, um den Inhalt der Zeichenfolge zu ändern
Versuchen wir nun, die Referenz zu ändern
Ausgabe:
Da der
the_string
Parameter als Wert übergeben wurde, hatte das Zuweisen einer neuen Zeichenfolge keine Auswirkung, die der Code außerhalb der Methode sehen konnte. Dasthe_string
war eine Kopie derouter_string
Referenz, und wir hattenthe_string
auf eine neue Zeichenfolge gezeigt, aber es gab keine Möglichkeit zu ändern, wo gezeigt wurdeouter_string
.Ich hoffe, das klärt die Dinge ein wenig auf.
BEARBEITEN: Es wurde festgestellt, dass dies nicht die Frage beantwortet, die @David ursprünglich gestellt hat: "Kann ich etwas tun, um die Variable als tatsächliche Referenz zu übergeben?". Lassen Sie uns daran arbeiten.
Wie kommen wir darum herum?
Wie die Antwort von @ Andrea zeigt, können Sie den neuen Wert zurückgeben. Dies ändert nichts an der Art und Weise, wie Dinge übergeben werden, aber Sie können die gewünschten Informationen wieder herausholen:
Wenn Sie die Verwendung eines Rückgabewerts wirklich vermeiden möchten, können Sie eine Klasse erstellen, die Ihren Wert enthält, und ihn an die Funktion übergeben oder eine vorhandene Klasse wie eine Liste verwenden:
Obwohl dies etwas umständlich erscheint.
quelle
def Foo(alist): alist = [1,2,3]
wird nicht den Inhalt der Liste der Anrufer Perspektive ändern.Das Problem ergibt sich aus einem Missverständnis der Variablen in Python. Wenn Sie an die meisten traditionellen Sprachen gewöhnt sind, haben Sie ein mentales Modell dessen, was in der folgenden Reihenfolge passiert:
Sie glauben, dass dies
a
ein Speicherort ist, in dem der Wert1
gespeichert und dann aktualisiert wird, um den Wert zu speichern2
. So funktioniert das in Python nicht.a
Beginnt vielmehr als Referenz auf ein Objekt mit dem Wert1
und wird dann als Referenz auf ein Objekt mit dem Wert neu zugewiesen2
. Diese beiden Objekte können weiterhin koexistieren, obwohl siea
sich nicht mehr auf das erste beziehen. Tatsächlich können sie von einer beliebigen Anzahl anderer Referenzen innerhalb des Programms geteilt werden.Wenn Sie eine Funktion mit einem Parameter aufrufen, wird eine neue Referenz erstellt, die auf das übergebene Objekt verweist. Dies unterscheidet sich von der Referenz, die im Funktionsaufruf verwendet wurde. Daher gibt es keine Möglichkeit, diese Referenz zu aktualisieren und auf a zu verweisen neues Objekt. In Ihrem Beispiel:
self.variable
ist eine Referenz auf das String-Objekt'Original'
. Wenn Sie aufrufenChange
, erstellen Sie einen zweiten Verweisvar
auf das Objekt. Innerhalb der Funktion weisen Sie die Referenzvar
einem anderen Zeichenfolgenobjekt zu'Changed'
, die Referenzself.variable
ist jedoch separat und ändert sich nicht.Der einzige Weg, dies zu umgehen, besteht darin, ein veränderliches Objekt zu übergeben. Da sich beide Referenzen auf dasselbe Objekt beziehen, werden alle Änderungen am Objekt an beiden Stellen wiedergegeben.
quelle
Ich fand die anderen Antworten ziemlich lang und kompliziert, deshalb habe ich dieses einfache Diagramm erstellt, um zu erklären, wie Python mit Variablen und Parametern umgeht.
quelle
B[0] = 2
vs. direkte Zuordnung ,B = 2
.A=B
oder bedeutenB=A
.Es ist weder Pass-by-Value noch Pass-by-Reference - es ist Call-by-Object. Siehe dies von Fredrik Lundh:
http://effbot.org/zone/call-by-object.htm
Hier ist ein wichtiges Zitat:
In Ihrem Beispiel wird beim Aufrufen der
Change
Methode ein Namespace dafür erstellt. undvar
wird innerhalb dieses Namespace zu einem Namen für das Zeichenfolgenobjekt'Original'
. Dieses Objekt hat dann einen Namen in zwei Namespaces. Als nächstes wirdvar = 'Changed'
anvar
ein neues Zeichenfolgenobjekt gebunden, und daher vergisst der Namespace der Methode'Original'
. Schließlich wird dieser Namespace vergessen und die Zeichenfolge'Changed'
mit.quelle
swap
Funktion anhängen, die zwei Referenzen wie diesea = [42] ; b = 'Hello'; swap(a, b) # Now a is 'Hello', b is [42]
Denken Sie an Dinge, die durch Zuweisung statt durch Referenz / Wert übergeben werden. Auf diese Weise ist immer klar, was passiert, solange Sie verstehen, was während der normalen Aufgabe passiert.
Wenn Sie also eine Liste an eine Funktion / Methode übergeben, wird die Liste dem Parameternamen zugewiesen. Das Anhängen an die Liste führt dazu, dass die Liste geändert wird. Durch das Neuzuweisen der Liste innerhalb der Funktion wird die ursprüngliche Liste nicht geändert, da:
Da unveränderliche Typen nicht geändert werden können, scheinen sie als Wert übergeben zu werden. Wenn Sie ein int an eine Funktion übergeben, wird das int dem Parameter der Funktion zugewiesen. Sie können das immer nur neu zuweisen, aber der ursprüngliche Variablenwert wird dadurch nicht geändert.
quelle
Effbot (auch bekannt als Fredrik Lundh) hat Pythons variablen Übergabestil als Call-by-Object beschrieben: http://effbot.org/zone/call-by-object.htm
Objekte werden auf dem Heap zugewiesen und Zeiger auf sie können überall herumgereicht werden.
Wenn Sie eine Zuweisung vornehmen, wie z. B.
x = 1000
, wird ein Wörterbucheintrag erstellt, der die Zeichenfolge "x" im aktuellen Namespace einem Zeiger auf das Ganzzahlobjekt zuordnet, das tausend enthält.Wenn Sie "x" mit aktualisieren
x = 2000
, wird ein neues ganzzahliges Objekt erstellt und das Wörterbuch so aktualisiert, dass es auf das neue Objekt zeigt. Das alte tausend Objekt ist unverändert (und kann lebendig sein oder nicht, je nachdem, ob sich etwas anderes auf das Objekt bezieht).Wenn Sie eine neue Aufgabe ausführen, z. B.
y = x
, wird ein neuer Wörterbucheintrag "y" erstellt, der auf dasselbe Objekt verweist wie der Eintrag für "x".Objekte wie Zeichenfolgen und Ganzzahlen sind unveränderlich . Dies bedeutet einfach, dass es keine Methoden gibt, mit denen das Objekt nach seiner Erstellung geändert werden kann. Wenn beispielsweise das ganzzahlige Objekt 1000 erstellt wurde, wird es sich nie mehr ändern. Für die Mathematik werden neue ganzzahlige Objekte erstellt.
Objekte wie Listen sind veränderbar . Dies bedeutet, dass der Inhalt des Objekts durch alles geändert werden kann, was auf das Objekt zeigt. Zum Beispiel
x = []; y = x; x.append(10); print y
wird gedruckt[10]
. Die leere Liste wurde erstellt. Sowohl "x" als auch "y" zeigen auf dieselbe Liste. Das Append- Methode mutiert (aktualisiert) das Listenobjekt (wie das Hinzufügen eines Datensatzes zu einer Datenbank) und das Ergebnis ist sowohl für "x" als auch für "y" sichtbar (genau wie eine Datenbankaktualisierung für jede Verbindung zu dieser Datenbank sichtbar wäre).Hoffe, das klärt das Problem für Sie.
quelle
id()
Funktion den Wert des Zeigers (Objektreferenz) zurückgibt, wie die Antwort von pepr nahe legt?Technisch, Python immer Pass-by-Referenzwerte . Ich werde meine andere Antwort wiederholen , um meine Aussage zu unterstützen.
Python verwendet immer Referenzwerte. Es gibt keine Ausnahme. Jede Variablenzuweisung bedeutet das Kopieren des Referenzwerts. Keine Ausnahmen. Jede Variable ist der Name, der an den Referenzwert gebunden ist. Immer.
Sie können sich einen Referenzwert als Adresse des Zielobjekts vorstellen. Die Adresse wird bei Verwendung automatisch dereferenziert. Auf diese Weise scheinen Sie beim Arbeiten mit dem Referenzwert direkt mit dem Zielobjekt zu arbeiten. Dazwischen gibt es immer eine Referenz, einen Schritt weiter, um zum Ziel zu springen.
Hier ist das Beispiel, das beweist, dass Python die Übergabe als Referenz verwendet:
Wenn das Argument als Wert übergeben wurde, wird das äußere
lst
nicht geändert werden. Das Grün sind die Zielobjekte (das Schwarz ist der darin gespeicherte Wert, das Rot ist der Objekttyp), das Gelb ist der Speicher mit dem Referenzwert im Inneren - gezeichnet als Pfeil. Der blaue durchgezogene Pfeil ist der Referenzwert, der an die Funktion übergeben wurde (über den gestrichelten blauen Pfeilpfad). Das hässliche Dunkelgelb ist das interne Wörterbuch. (Es könnte tatsächlich auch als grüne Ellipse gezeichnet werden. Die Farbe und die Form sagen nur, dass es intern ist.)Du kannst den ... benutzen
id()
integrierten Funktion den Referenzwert (dh die Adresse des Zielobjekts) ermitteln.In kompilierten Sprachen ist eine Variable ein Speicherplatz, der den Wert des Typs erfassen kann. In Python ist eine Variable ein Name (intern als Zeichenfolge erfasst), der an die Referenzvariable gebunden ist, die den Referenzwert für das Zielobjekt enthält. Der Name der Variablen ist der Schlüssel im internen Wörterbuch. Der Werteteil dieses Wörterbuchelements speichert den Referenzwert für das Ziel.
Referenzwerte sind in Python ausgeblendet. Es gibt keinen expliziten Benutzertyp zum Speichern des Referenzwerts. Sie können jedoch ein Listenelement (oder ein Element in einem anderen geeigneten Containertyp) als Referenzvariable verwenden, da alle Container die Elemente auch als Verweise auf die Zielobjekte speichern. Mit anderen Worten, Elemente sind tatsächlich nicht im Container enthalten - nur die Verweise auf Elemente.
quelle
In Python gibt es keine Variablen
Der Schlüssel zum Verständnis der Parameterübergabe besteht darin, nicht mehr an "Variablen" zu denken. Es gibt Namen und Objekte in Python und zusammen erscheinen sie wie Variablen, aber es ist nützlich, die drei immer zu unterscheiden.
Das ist alles was dazu gehört. Die Veränderlichkeit spielt für diese Frage keine Rolle.
Beispiel:
Dadurch wird der Name
a
an ein Objekt vom Typ Integer gebunden, das den Wert 1 enthält.Dies bindet den Namen
b
an dasselbe Objektx
gebunden, an das der Name derzeit gebunden ist. Danach hat der Nameb
nichts mehr mit dem Namen zu tunx
.Siehe Abschnitte 3.1 und 4.2 in der Python 3-Sprachreferenz.
Wie lese ich das Beispiel in der Frage?
In dem in der Frage gezeigten Code
self.Change(self.variable)
bindet die Anweisung den Namenvar
(im FunktionsumfangChange
) an das Objekt, das den Wert'Original'
und die Zuordnung enthältvar = 'Changed'
(im FunktionskörperChange
) weist denselben Namen erneut zu: einem anderen Objekt (das passiert) auch eine Saite zu halten, hätte aber etwas ganz anderes sein können).Wie man als Referenz weitergibt
Wenn das zu ändernde Objekt also ein veränderliches Objekt ist, gibt es kein Problem, da alles effektiv als Referenz übergeben wird.
Wenn es sich um ein unveränderliches Objekt handelt (z. B. ein Bool, eine Zahl, eine Zeichenfolge), müssen Sie es in ein veränderliches Objekt einschließen.
Die schnelle und schmutzige Lösung hierfür ist eine Ein-Element-Liste (anstelle von
self.variable
, übergeben[self.variable]
und in der Funktion ändernvar[0]
).Der pythonischere Ansatz wäre die Einführung einer trivialen Klasse mit einem Attribut. Die Funktion empfängt eine Instanz der Klasse und bearbeitet das Attribut.
quelle
int
eine Variable deklariert wird, aberInteger
nicht. Beide deklarieren Variablen. DieInteger
Variable ist ein Objekt, dieint
Variable ist ein Grundelement. Als Beispiel haben Sie anhand der Darstellung gezeigt, wie Ihre Variablen funktionierena = 1; b = a; a++ # doesn't modify b
. Das gilt auch für Python (mit,+= 1
da es++
in Python keine gibt )!Ein einfacher Trick, den ich normalerweise benutze, besteht darin, ihn einfach in eine Liste zu packen:
(Ja, ich weiß, dass dies unpraktisch sein kann, aber manchmal ist es einfach genug, dies zu tun.)
quelle
(Bearbeiten - Blair hat seine äußerst beliebte Antwort so aktualisiert, dass sie jetzt korrekt ist.)
Ich denke, es ist wichtig anzumerken, dass der aktuelle Beitrag mit den meisten Stimmen (von Blair Conrad), obwohl er in Bezug auf sein Ergebnis korrekt ist, irreführend ist und aufgrund seiner Definitionen grenzwertig falsch ist. Obwohl es viele Sprachen (wie C) gibt, in denen der Benutzer entweder als Referenz oder als Wert übergeben kann, gehört Python nicht dazu.
Die Antwort von David Cournapeau verweist auf die wahre Antwort und erklärt, warum das Verhalten in Blair Conrads Beitrag korrekt zu sein scheint, während die Definitionen nicht korrekt sind.
In dem Maße, in dem Python als Wert übergeben wird, werden alle Sprachen als Wert übergeben, da einige Daten (sei es ein "Wert" oder eine "Referenz") gesendet werden müssen. Dies bedeutet jedoch nicht, dass Python in dem Sinne als Wert übergeben wird, wie es ein C-Programmierer denken würde.
Wenn Sie das Verhalten wollen, ist Blair Conrads Antwort in Ordnung. Wenn Sie jedoch wissen möchten, warum Python weder als Wert noch als Referenz übergeben wird, lesen Sie die Antwort von David Cournapeau.
quelle
void swap(int& x, int& y) { int temp = x; x = y; y = temp; }
werden beispielsweise die übergebenen Variablen ausgetauscht. In Pascal verwenden Sievar
anstelle von&
.Sie haben hier einige wirklich gute Antworten.
quelle
In diesem Fall wird der
var
in der Methode betitelten VariablenChange
ein Verweis zugewiesenself.variable
, und Sie weisen sofort eine Zeichenfolge zuvar
. Es zeigt nicht mehr aufself.variable
. Das folgende Codefragment zeigt, was passieren würde, wenn Sie die Datenstruktur ändern, auf die durchvar
undself.variable
in diesem Fall eine Liste verwiesen wird :Ich bin sicher, jemand anderes könnte dies weiter klären.
quelle
Das Pass-by-Assignment-Schema von Python ist nicht ganz das gleiche wie die Referenzparameteroption von C ++, aber es stellt sich heraus, dass es dem Argument-Passing-Modell der C-Sprache (und anderer) in der Praxis sehr ähnlich ist:
quelle
Wie Sie sagen können, benötigen Sie ein veränderbares Objekt, aber ich möchte Ihnen vorschlagen, die globalen Variablen zu überprüfen, da sie Ihnen helfen oder sogar diese Art von Problem lösen können!
http://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python
Beispiel:
quelle
Viele Einblicke in die Antworten hier, aber ich denke, ein zusätzlicher Punkt wird hier nicht explizit erwähnt. Zitieren aus der Python-Dokumentation https://docs.python.org/2/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python
"In Python sind Variablen, auf die nur innerhalb einer Funktion verwiesen wird, implizit global. Wenn einer Variablen irgendwo im Funktionskörper ein neuer Wert zugewiesen wird, wird davon ausgegangen, dass es sich um einen lokalen Wert handelt. Wenn einer Variablen jemals ein neuer Wert innerhalb der Funktion zugewiesen wird, Die Variable ist implizit lokal, und Sie müssen sie explizit als "global" deklarieren. Obwohl dies zunächst etwas überraschend ist, erklärt eine kurze Überlegung dies. Einerseits bietet das Erfordernis "global" für zugewiesene Variablen einen Balken gegen unbeabsichtigte Nebenwirkungen Wenn andererseits global für alle globalen Referenzen erforderlich wäre, würden Sie immer global verwenden. Sie müssten jede Referenz auf eine integrierte Funktion oder auf eine Komponente eines importierten Moduls als global deklarieren. Diese Unordnung würde die Nützlichkeit der globalen Erklärung zur Identifizierung von Nebenwirkungen zunichte machen. "
Dies gilt auch dann, wenn ein veränderliches Objekt an eine Funktion übergeben wird. Und mir erklärt klar den Grund für den Unterschied im Verhalten zwischen der Zuordnung zum Objekt und der Bearbeitung des Objekts in der Funktion.
gibt:
Die Zuweisung zu einer globalen Variablen, die nicht als global deklariert ist, erstellt daher ein neues lokales Objekt und unterbricht die Verknüpfung zum ursprünglichen Objekt.
quelle
Hier ist die einfache (ich hoffe) Erklärung des
pass by object
in Python verwendeten Konzepts .Immer wenn Sie ein Objekt an die Funktion übergeben, wird das Objekt selbst übergeben (Objekt in Python ist tatsächlich das, was Sie in anderen Programmiersprachen als Wert bezeichnen würden), nicht der Verweis auf dieses Objekt. Mit anderen Worten, wenn Sie anrufen:
Das eigentliche Objekt - [0, 1] (das in anderen Programmiersprachen als Wert bezeichnet wird) wird übergeben. Tatsächlich wird die Funktion also
change_me
versuchen, Folgendes zu tun:Dadurch wird das an die Funktion übergebene Objekt offensichtlich nicht geändert. Wenn die Funktion so aussah:
Dann würde der Anruf ergeben:
was offensichtlich das Objekt ändern wird. Diese Antwort erklärt es gut.
quelle
list = [1, 2, 3]
Ursachen , die die Wiederverwendung vonlist
Namen für etwas anderes und forgeting das ursprünglich übergebene Objekt. Sie können es jedoch versuchenlist[:] = [1, 2, 3]
(übrigenslist
ist der falsche Name für eine Variable. Nachdenken[0, 1] = [1, 2, 3]
ist ein völliger Unsinn. Was bedeutet Ihrer Meinung nach , dass das Objekt selbst übergeben wird ? Was wird Ihrer Meinung nach in die Funktion kopiert?[0, 1] = [1, 2, 3]
ist einfach ein schlechtes Beispiel. In Python gibt es nichts Vergleichbares.alist[2]
zählt als Name eines dritten Elistenelements. Aber ich glaube, ich habe falsch verstanden, was Ihr Problem war. :-)Abgesehen von all den tollen Erklärungen, wie dieses Zeug in Python funktioniert, sehe ich keinen einfachen Vorschlag für das Problem. Wenn Sie scheinbar Objekte und Instanzen erstellen, können Sie Instanzvariablen auf folgende Weise pythonisch verarbeiten und ändern:
In Instanzmethoden beziehen Sie sich normalerweise auf
self
den Zugriff auf Instanzattribute. Es ist normal, Instanzattribute in Instanzmethoden festzulegen__init__
und diese zu lesen oder zu ändern. Deshalb geben Sie auchself
als erstes Argument andef Change
.Eine andere Lösung wäre, eine statische Methode wie diese zu erstellen:
quelle
Es gibt einen kleinen Trick, um ein Objekt als Referenz zu übergeben, obwohl die Sprache dies nicht ermöglicht. Es funktioniert auch in Java, es ist die Liste mit einem Element. ;-);
Es ist ein hässlicher Hack, aber es funktioniert. ;-P
quelle
p
ist eine Referenz auf ein veränderbares Listenobjekt, in dem das Objekt gespeichert istobj
. Die Referenz 'p' wird übergebenchangeRef
. Im InnerenchangeRef
wird eine neue Referenz erstellt (die neue Referenz wird aufgerufenref
), die auf dasselbe Listenobjekt verweist, auf das verwiesen wirdp
. Da Listen jedoch veränderbar sind, sind Änderungen an der Liste für beide Referenzen sichtbar . In diesem Fall haben Sie dieref
Referenz verwendet, um das Objekt am Index 0 so zu ändern, dass es anschließend dasPassByReference('Michael')
Objekt speichert . Die Änderung am Listenobjekt wurde mit vorgenommenref
, diese Änderung ist jedoch für sichtbarp
.p
undref
verweisen nun auf ein Listenobjekt, in dem das einzelne Objekt gespeichert istPassByReference('Michael')
. Daraus folgt, dassp[0].name
zurückkehrtMichael
. Natürlichref
ist jetzt aus dem Rahmen gegangen und kann Müll gesammelt werden, aber trotzdem.name
des ursprünglichenPassByReference
Objekts, das der Referenz zugeordnet istobj
, nicht geändert . In der Tatobj.name
wird zurückkehrenPeter
. Die oben genannten Kommentare setzen die Definition vorausMark Ransom
.PassByReference
Objekt durch ein anderesPassByReference
Objekt in Ihrer Liste ersetzt und auf das letztere der beiden Objekte verwiesen.Ich habe die folgende Methode verwendet, um schnell ein paar Fortran-Codes in Python zu konvertieren. Es ist wahr, dass es nicht als Referenz dient, da die ursprüngliche Frage gestellt wurde, sondern in einigen Fällen eine einfache Lösung ist.
quelle
dict
und dann die zurückgibtdict
. Während der Reinigung kann sich jedoch herausstellen, dass ein Teil des Systems neu aufgebaut werden muss. Daher muss die Funktion nicht nur das Gereinigte zurückgeben,dict
sondern auch den Wiederaufbau signalisieren können. Ich habe versucht, einebool
Referenz zu übergeben, aber das funktioniert natürlich nicht. Als ich herausfand, wie ich das lösen kann, fand ich, dass Ihre Lösung (im Grunde genommen ein Tupel zurück) am besten funktioniert und gleichzeitig überhaupt kein Hack / Workaround ist (IMHO).Während das Übergeben von Referenzen nichts ist, was gut in Python passt und selten verwendet werden sollte, gibt es einige Problemumgehungen, mit denen das aktuell einer lokalen Variablen zugewiesene Objekt abgerufen oder sogar eine lokale Variable innerhalb einer aufgerufenen Funktion neu zugewiesen werden kann.
Die Grundidee besteht darin, eine Funktion zu haben, die diesen Zugriff ermöglicht und als Objekt an andere Funktionen übergeben oder in einer Klasse gespeichert werden kann.
Eine Möglichkeit ist die Verwendung
global
(für globale Variablen) odernonlocal
(für lokale Variablen in einer Funktion) in einer Wrapper-Funktion zu verwenden.Die gleiche Idee funktioniert beim Lesen und
del
Ätzen einer Variablen.Zum Lesen gibt es sogar eine kürzere Möglichkeit, nur zu verwenden
lambda: x
der ein Callable zurückgegeben wird, der beim Aufruf den aktuellen Wert von x zurückgibt. Dies ist etwas wie "Call by Name", das in Sprachen in der fernen Vergangenheit verwendet wurde.Das Übergeben von 3 Wrappern für den Zugriff auf eine Variable ist etwas unhandlich, sodass diese in eine Klasse mit einem Proxy-Attribut eingeschlossen werden können:
Die Pythons "Reflection" -Unterstützung ermöglicht es, ein Objekt zu erhalten, das einen Namen / eine Variable in einem bestimmten Bereich neu zuweisen kann, ohne Funktionen explizit in diesem Bereich zu definieren:
Hier
ByRef
schließt die Klasse einen Wörterbuchzugriff ein. Der Attributzugriff aufwrapped
wird also in einen Elementzugriff im übergebenen Wörterbuch übersetzt. Durch Übergeben des Ergebnisses des eingebautenlocals
und des Namens einer lokalen Variablen wird auf eine lokale Variable zugegriffen . Die Python-Dokumentation ab 3.5 weist darauf hin, dass das Ändern des Wörterbuchs möglicherweise nicht funktioniert, aber für mich zu funktionieren scheint.quelle
Angesichts der Art und Weise, wie Python mit Werten umgeht und auf diese verweist, können Sie ein beliebiges Instanzattribut nur nach Namen referenzieren:
In echtem Code würden Sie natürlich eine Fehlerprüfung bei der Diktatsuche hinzufügen.
quelle
Da Wörterbücher als Referenz übergeben werden, können Sie eine dict-Variable verwenden, um darin referenzierte Werte zu speichern.
quelle
Pass-By-Reference in Python unterscheidet sich erheblich vom Konzept der Pass-By-Reference in C ++ / Java.
quelle
Da Ihr Beispiel zufällig objektorientiert ist, können Sie die folgenden Änderungen vornehmen, um ein ähnliches Ergebnis zu erzielen:
quelle
Sie können lediglich eine leere Klasse als Instanz zum Speichern von Referenzobjekten verwenden, da intern Objektattribute in einem Instanzwörterbuch gespeichert werden. Siehe das Beispiel.
quelle
Da es nirgends erwähnt zu werden scheint, besteht ein Ansatz zur Simulation von Referenzen, wie er beispielsweise aus C ++ bekannt ist, darin, eine "Update" -Funktion zu verwenden und diese anstelle der tatsächlichen Variablen (oder besser "Name") zu übergeben:
Dies ist meistens nützlich für "Nur-Out-Referenzen" oder in einer Situation mit mehreren Threads / Prozessen (indem die Aktualisierungsfunktion Thread / Multiprocessing sicher gemacht wird).
Offensichtlich erlaubt das Obige nicht, den Wert zu lesen , sondern nur zu aktualisieren.
quelle