2012-06-27 5 views
33

Im CodePython variable Referenzzuordnung

y = 7 
x = y  
x = 8 

Nun wird y 7 und x 8 sein wird, aber eigentlich will ich ändern y. Kann ich die Referenz von y zuweisen und das tun?

Zum Beispiel in C++ dasselbe, wie erreicht werden kann,

int y = 8; 
int &x = y; 
x = 9; 

Nun sind beide y & x wird 9

Antwort

44

Nein, können Sie nicht. Wie andere Antworten darauf hinweisen, können Sie (ab?) Das Aliasing von veränderbaren Objekten verwenden, um einen ähnlichen Effekt zu erzielen. Das ist jedoch nicht dasselbe wie C++ - Referenzen, und ich möchte erklären, was tatsächlich geschieht, um Missverständnisse zu vermeiden. In C++ (und anderen Sprachen) sehen Sie, dass eine Variable (und Objektfelder sowie Einträge in Auflistungen usw.) ein Speicherort ist und Sie einen Wert schreiben (z. B. eine ganze Zahl, ein Objekt oder ein Zeiger) auf diesen Ort. In diesem Modell sind Verweise ein Alias ​​für einen Speicherort (beliebiger Art). Wenn Sie einer Nicht-Verweisvariablen zuweisen, kopieren Sie einen Wert (auch wenn es sich nur um einen Zeiger handelt, immer noch um einen Wert) für den Speicherort. Wenn Sie eine Referenz zuweisen, kopieren Sie sie an einen anderen Speicherort. Beachten Sie, dass Sie eine Referenz nicht selbst ändern können - sobald sie gebunden ist (und sie muss, sobald Sie eine erstellen), ändern alle Zuweisungen nicht die Referenz, sondern was auch immer gemeint ist.

In Python (und anderen Sprachen) ist eine Variable (und Objektfelder und Einträge in Sammlungen usw.) nur ein Name. Werte sind irgendwo else (z. B. über den gesamten Heap verstreut), und eine Variable verweist auf einen Wert (nicht im Sinne von C++ - Verweisen, eher wie ein Zeiger minus die Zeigerarithmetik). Mehrere Namen können sich auf denselben Wert beziehen (was im Allgemeinen eine gute Sache ist). Python (und andere Sprachen) ruft alles auf, was benötigt wird, um auf einen Wert als Verweis Bezug zu nehmen, obwohl es mit Dingen wie C++ Referenzen und Pass-by-Reference nicht verwandt ist. Wenn Sie einer Variablen (oder einem Objektfeld oder ...) zuweisen, wird einfach auf einen anderen Wert verwiesen.Das gesamte Modell der Speicherorte gilt nicht für Python, der Programmierer behandelt niemals Speicherorte für Werte. Alles, was er speichert und mischt, sind Python-Referenzen, und diese sind keine Werte in Python, daher können sie nicht Ziel anderer Python-Referenzen sein.

All dies ist unabhängig von der Veränderlichkeit des Wertes - es ist zum Beispiel für Ints und Listen gleich. Sie können keine Variable verwenden, die auf eines der Objekte verweist, und das Objekt, auf das es zeigt, überschreiben. Sie können das Objekt nur anweisen, Teile von sich selbst zu ändern - sagen wir, ändern Sie eine Referenz, die es enthält.

Ist das ein restriktiveres Modell? Vielleicht, aber die meiste Zeit ist es stark genug. Und wenn das nicht der Fall ist, können Sie es umgehen, entweder mit einer benutzerdefinierten Klasse wie der unten angegebenen oder (äquivalent, aber weniger offensichtlich) einer Sammlung mit einem einzelnen Element.

class Reference: 
    def __init__(self, val): 
     self._value = val # just refers to val, no copy 

    def get(self): 
     return self._value 

    def set(self, val): 
     self._value = val 

Das wird noch nicht zulassen, dass Sie ein „normales“ Variable oder Objektfeld an Alias, aber Sie können mehrere Variablen auf das gleiche Reference Objekt verweisen (dito für die wandelbare-Singleton-Sammlung Alternative). Sie müssen nur darauf achten, immer .get()/.set() (oder [0]) zu verwenden.

+2

Gute Erklärung, +1 für die Klärung, dass es nichts mit Wandelbarkeit zu tun hat. –

11

Nein, Python diese Funktion nicht haben.

Wenn Sie haben eine Liste (oder ein anderes veränderliches Objekt) könnten Sie tun, was Sie wollen, indem Sie das Objekt mutiert, dass beide x und y sind gebunden an:

>>> x = [7] 
>>> y = x 
>>> y[0] = 8 
>>> print x 
[8] 

es Siehe Arbeits online: ideone

+1

Obwohl dies wirklich hilfreich ist, gibt es bei dieser "Mutation" eines einfachen numerischen Wertes mehr oder weniger große Nachteile. Wenn Sie die Ganzzahl in einer Liste mit einem einzelnen Element ändern, benötigen Sie etwas mehr als das Dreifache des normalerweise benötigten Speicherplatzes. Beispiel (Ich werde sys.getsizeof (...) verwenden, um den Größenunterschied zu veranschaulichen): x = 1 -> sys.getsizeof (x) -> geben Sie uns 14 -> x = [1] -> sys.getsizeof (x) -> gibt uns 36 – rbaleksandar

5

Sie sollten dafür ein veränderbares Objekt verwenden.

in Python x & y sind nur Verweise auf Objekte so y = 7 y Punkte auf dem Objekt 7 bedeutet. x=y bedeutet x auch Punkte zu 7, sondern als 7 unveränderlich ist, so den Wert von x ändert ändert das Objekt einfach 7 und y noch 7 zeigen bleibt.

>>> y = [7] 
>>> x = y 
>>> x[0] = 8 # here you're changing [7] not x or y, x & y are just references to [7] 
>>> y 
[8] 
+0

Sie wollten darauf hinweisen, dass y auch nach der Änderung von x unverändert bleibt, aber das ist nicht, was Sie hier geschrieben haben. Bitte klären Sie. –

1

Alternativ können Sie einen selbst gestalteten Container verwenden.

class Value(object): 
    def __init__(self, value): self.value = value 

y = Value(7) 
x = y 
x.value = 8 
print y.value 

ideone