2017-01-17 3 views
2

Python verwendet Namen, um Objekte zu referenzieren. Wenn wir a = b, a und b sagen, beziehen wir uns jetzt auf das gleiche Objekt, und wenn wir a ändern, werden wir die gleiche Änderung in b sehen. Zum Beispiel:Wann erstellt Python ein neues Objekt?

a = [1, 2, 3] 
b = a 

a.append(4) 

print(b) 

wird gedruckt [1, 2, 3, 4].

Einige Operationen erstellen jedoch neue Objekte. Zum Beispiel:

a = 1 
b = a 

a = a + 1 

print(b) 

wird 1 drucken. Offensichtlich erzeugt die Zeile a = a + 1 irgendwie ein neues Objekt mit einem Wert von a + 1 und bindet den Namen a daran. Wie funktioniert das? Was ist der Mechanismus, der in diesem Fall ein neues Objekt erzeugt?

Diese Frage ist kein Duplikat von this one, da ich speziell frage, wie die Objekterstellung in diesem Fall passiert, während die andere Frage allgemeiner war, wenn Namen Objekte teilen.

+2

Listen sind veränderbar (verwenden Sie 'copy' oder slicing mit' [:] ', um sie zu kopieren), ganze Zahlen sind unveränderlich (sie werden jedes Mal neu erstellt, wie Strings) –

+4

Mögliche Duplikate von [Wie python weist Werte nach Zuweisungsoperator] (http://stackoverflow.com/questions/34521078/how-does-python-assign-values-after-assignment-operator) –

+0

Technisch bin ich mir nicht sicher, dass 'a = a + 1' * erstellt * ein neues Objekt in diesem speziellen Fall, da Python ganze Zahlen im Bereich [-5, 256] zwischenspeichert. Ich denke eher, dass ein vorher erstelltes Integer-Objekt aus dem Cache einem 'a' zugewiesen wird. Mit anderen Worten, "a" zeigt jetzt auf ein anderes Objekt als "b", aber in dieser Anweisung wurde kein Objekt erstellt. Korrigiere mich, wenn ich falsch liege. – Tagc

Antwort

0

Ich fand die Informationen, die ich auf der Mechanik der Objekterstellung in Luciano Ramalhos Buch Fluent Python suchte.

Ramalho erklärt, dass während __init__ in der Regel als "Konstruktor" betrachtet wird, tatsächlich Objekte durch Aufruf der __new__ Methode erstellt werden. Es ist eine Klassenmethode und gibt eine Instanz einer Klasse zurück, die als erstes Argument an __init__ übergeben wird (konventionell "self"). Daher ist __init__ der Initialisierer, nicht der Konstruktor.

Dies kann mit dem folgenden Beispiel veranschaulicht werden:

class C(object): 
    def __new__(cls): 
     new_inst = object.__new__(cls) 
     print new_inst.__dict__ 
     new_inst.var_1 = 1 
     return new_inst 

    def __init__(self): 
     print self.__dict__ 
     self.var_2 = 2 

a = C()    # Prints: 
         # {} 
         # {'var_1': 1} 
print a.__dict__ # returns {'var_2': 2, 'var_1': 1} 

b = C.__new__(C) # Prints: 
         # {} 
print b.__dict__ # returns {'var_1': 1} 

b.__init__()  # Prints: 
         # {'var_2': 2, 'var_1': 1} 
print b.__dict__ # returns {'var_2': 2, 'var_1': 1} 

Die Linie a = C()__new__ von __init__ gefolgt ruft, wie wir aus den Ausdrucken von __dict__ sehen können. Dies kann in separate Aufrufe aufgeteilt werden, wie mit dem Objekt b gezeigt.

This question ist ebenfalls relevant.

+1

Da Sie das OP sind, liegt es an Ihnen zu entscheiden, ob es richtig oder falsch ist, aber ich glaube nicht, dass Sie Ihre eigene Frage wirklich beantwortet haben. Es bleibt noch zu erklären, warum 'a = b' in einigen Fällen (z. B. große ganze Zahlen) ein neues Objekt erzeugen kann, aber nicht in anderen (z. B. Listen).Ist es beispielsweise möglich, '__new__' oder die Metaklasse einer Klasse zu optimieren, um ein" primitives "Verhalten für benutzerdefinierte Klassen zu reproduzieren? – jdehesa

+0

Sie haben Recht, es ist wahrscheinlich eine unvollständige Antwort. Es hilft mir jedoch, die "Mechanik der Objekterzeugung" zu verstehen, auf die ich in der Frage hingewiesen habe, auf die ich am meisten neugierig war. – PProteus

Verwandte Themen