3290 Stimmen

Wie übergebe ich eine Variable per Referenz?

Werden die Parameter als Referenz oder als Wert übergeben? Wie übergebe ich per Referenz, so dass der folgende Code Folgendes ausgibt 'Changed' anstelle von 'Original' ?

class PassByReference:
    def __init__(self):
        self.variable = 'Original'
        self.change(self.variable)
        print(self.variable)

    def change(self, var):
        var = 'Changed'

32 Stimmen

Eine kurze Erklärung/Klarstellung finden Sie in der ersten Antwort auf diese Stackoverflow-Frage . Da Zeichenketten unveränderlich sind, werden sie nicht geändert und es wird eine neue Variable erstellt, so dass die "äußere" Variable immer noch denselben Wert hat.

11 Stimmen

Der Code in BlairConrads Antwort ist gut, aber die Erklärung von DavidCournapeau und DarenThomas ist richtig.

79 Stimmen

Bevor Sie die ausgewählte Antwort lesen, sollten Sie diesen kurzen Text lesen Andere Sprachen haben "Variablen", Python hat "Namen". . Denken Sie an "Namen" und "Objekte" anstelle von "Variablen" und "Referenzen" und Sie sollten viele ähnliche Probleme vermeiden.

28voto

bobobobo Punkte 61051

Sie haben hier einige wirklich gute Antworten erhalten.

x = [ 2, 4, 4, 5, 5 ]
print x  # 2, 4, 4, 5, 5

def go( li ) :
  li = [ 5, 6, 7, 8 ]  # re-assigning what li POINTS TO, does not
  # change the value of the ORIGINAL variable x

go( x ) 
print x  # 2, 4, 4, 5, 5  [ STILL! ]

raw_input( 'press any key to continue' )

3 Stimmen

Ja, aber wenn Sie x = [ 2, 4, 4, 5, 5], y = x, X[0] = 1 , print x # [1, 4 ,4, 5, 5] print y # [1, 4, 4, 5, 5]

0 Stimmen

X[0] oder x[0] ? verstehe ich nicht

22voto

Mike Mazur Punkte 2459

In diesem Fall ist die Variable mit dem Titel var in der Methode Change wird ein Verweis auf self.variable und Sie weisen sofort eine Zeichenkette zu var . Es zeigt nicht mehr auf self.variable . Der folgende Codeausschnitt zeigt, was passiert, wenn Sie die Datenstruktur ändern, auf die der Parameter var y self.variable , in diesem Fall eine Liste:

>>> class PassByReference:
...     def __init__(self):
...         self.variable = ['Original']
...         self.change(self.variable)
...         print self.variable
...         
...     def change(self, var):
...         var.append('Changed')
... 
>>> q = PassByReference()
['Original', 'Changed']
>>> 

Ich bin sicher, dass jemand anderes dies näher erläutern kann.

22voto

ajknzhol Punkte 6036

Pythons "pass-by-assignment"-Schema ist nicht ganz dasselbe wie C++'s "reference parameters"-Option, aber es stellt sich heraus, dass es in der Praxis dem "argument-passing"-Modell der Sprache C (und anderer) sehr ähnlich ist:

  • Unveränderliche Argumente werden effektiv übergeben " nach Wert ." Objekte wie Integer und Strings werden per Objektreferenz statt durch Kopieren übergeben, aber da man unveränderliche Objekte ohnehin nicht an Ort und Stelle ändern kann, ist der Effekt ähnlich wie bei einer Kopie.
  • Veränderliche Argumente werden effektiv übergeben " per Zeiger ." Objekte wie Listen und Dictionaries werden ebenfalls per Objektreferenz übergeben, was der Art und Weise ähnlich ist, wie C Arrays als Zeiger übergibt - veränderbare Objekte können an Ort und Stelle in der Funktion geändert werden, ähnlich wie C-Arrays.

19voto

Joop Punkte 7194

Viele Einsichten in den Antworten hier, aber ich denke, ein zusätzlicher Punkt wird hier nicht explizit erwähnt. Ich zitiere 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, die nur innerhalb einer Funktion referenziert werden, implizit global. Wenn einer Variablen irgendwo innerhalb des Funktionskörpers ein neuer Wert zugewiesen wird, wird angenommen, dass sie eine lokale Variable ist. Wenn einer Variablen innerhalb der Funktion ein neuer Wert zugewiesen wird, ist die Variable implizit lokal, und Sie müssen sie explizit als "global" deklarieren. Das ist zwar zunächst etwas überraschend, aber wenn man einen Moment darüber nachdenkt, erklärt sich dies. Einerseits bietet die Forderung nach "global" für zugewiesene Variablen einen Schutz vor unbeabsichtigten Nebeneffekten. Andererseits, wenn global für alle globalen Referenzen erforderlich wäre, würden Sie ständig global verwenden. Man müsste jeden Verweis auf eine eingebaute Funktion oder auf eine Komponente eines importierten Moduls als global deklarieren. Dieses Durcheinander würde den Nutzen der globalen Deklaration zur Erkennung von Seiteneffekten zunichte machen."

Auch bei der Übergabe eines veränderbaren Objekts an eine Funktion gilt dies. Und für mich erklärt dies eindeutig den Grund für den Unterschied im Verhalten zwischen der Zuweisung an das Objekt und der Bearbeitung des Objekts in der Funktion.

def test(l):
    print "Received", l , id(l)
    l = [0, 0, 0]
    print "Changed to", l, id(l)  # New local object created, breaking link to global l

l= [1,2,3]
print "Original", l, id(l)
test(l)
print "After", l, id(l)

gibt:

Original [1, 2, 3] 4454645632
Received [1, 2, 3] 4454645632
Changed to [0, 0, 0] 4474591928
After [1, 2, 3] 4454645632

Die Zuweisung an eine globale Variable, die nicht als global deklariert ist, erzeugt daher ein neues lokales Objekt und unterbricht die Verknüpfung mit dem ursprünglichen Objekt.

0 Stimmen

+1 gute Antwort, die genau das erwähnt, was ich gedacht habe. Ich war ziemlich überrascht, als niemand dies erwähnt hat. Wenn keine Zuweisung vorgenommen wird, sind der Alias und das Original eins, aber wenn wir eine Neuzuweisung vornehmen, wird die Verbindung unterbrochen und ein neues lokales Objekt innerhalb der Funktion erstellt.

18voto

Nuno Aniceto Punkte 1652

Wie Sie angeben können, müssen Sie ein veränderbares Objekt haben, aber lassen Sie mich Ihnen vorschlagen, über 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

ejemplo:

>>> def x(y):
...     global z
...     z = y
...

>>> x
<function x at 0x00000000020E1730>
>>> y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
>>> z
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'z' is not defined

>>> x(2)
>>> x
<function x at 0x00000000020E1730>
>>> y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
>>> z
2

5 Stimmen

Ich war versucht, eine ähnliche Antwort zu posten - der ursprüngliche Fragesteller hat vielleicht nicht gewusst, dass er eigentlich eine globale Variable verwenden wollte, die von allen Funktionen gemeinsam genutzt wird. Hier ist der Link, den ich geteilt hätte: stackoverflow.com/questions/423379/ Um @Tim zu antworten: Stack Overflow ist nicht nur eine Frage- und Antwort-Website, sondern auch ein riesiger Fundus an Referenzwissen, der nur mit mehr Input stärker und nuancierter wird - ähnlich wie ein aktives Wiki.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X