Da ich fast ein Anfänger in Python bin, werde ich mir zuerst die Klasse (so etwas wie eine Gewohnheit) mit einfachem Code ansehen.
class sampleCls():
pass
Definieren Sie eine leere Klasse. Wenn Sie versuchen, die Mitglieder der Klasse in diesem Status auszugeben,
from pprint import pprint
class sampleCls():
pass
pprint (inspect.getmembers(sampleCls))
Wenn du rennst
[('__doc__', None), ('__module__', '__main__')]
So was.
Fügen Sie eine Zeile hinzu (anstatt zu übergeben).
class sampleCls():
abc = 111
pprint (inspect.getmembers(sampleCls))
Wenn du rennst
[('__doc__', None), ('__module__', '__main__'), ('abc', 111)]
So was.
Nach dem Übergeben der Klassendefinition wird ein Klassenobjekt erstellt. Klassenobjekte können geändert werden. Versuchen Sie, das Klassenobjekt zu ändern, ohne noch eine Instanz zu erstellen.
class sampleCls():
abc = 111
#sampleCls.def = 222
sampleCls.efg = 222
pprint (inspect.getmembers(sampleCls))
[('__doc__', None), ('__module__', '__main__'), ('abc', 111), ('efg', 222)]
Sie können es so ändern. (In sampleCls.def ist def ein reserviertes Wort und es tritt ein Fehler auf (; ´∀ `))
Wenn Sie in diesem Status eine Instanz dieser Klasse erstellen,
class sampleCls():
abc = 111
sampleCls.efg = 222
i = sampleCls()
pprint (inspect.getmembers(sampleCls))
print "------------------------------"
pprint (inspect.getmembers(i))
[('__doc__', None), ('__module__', '__main__'), ('abc', 111), ('efg', 222)]
------------------------------
[('__doc__', None), ('__module__', '__main__'), ('abc', 111), ('efg', 222)]
Mit diesem Gefühl wird das später hinzugefügte efg auch in die Instanz aufgenommen. Sie können übrigens auch Variablen aus Klassenobjekten löschen.
class sampleCls():
abc = 111
sampleCls.efg = 222
pprint (inspect.getmembers(sampleCls))
print "------------------------------"
del sampleCls.abc
pprint (inspect.getmembers(sampleCls))
Wenn du rennst
[('__doc__', None), ('__module__', '__main__'), ('abc', 111), ('efg', 222)]
------------------------------
[('__doc__', None), ('__module__', '__main__'), ('efg', 222)]
Es ist weg. Dieser Bereich ähnelt JavaScript.
Die folgende Site besagt, dass Python keinen Konstruktor hat.
Auch so etwas wurde in das Buch geschrieben. [* 1](# 1) </ sub> Was die Definition des Konstruktors betrifft, so scheint es, dass die Speicherzuweisung auch vom Konstruktor vorgenommen wird.
Unter dem Gesichtspunkt der Programmierung ist die Speicherzuweisung in die Sprache integriert, sodass Instanzen initialisiert werden können. Daher dachte ich, es wäre in Ordnung, init als allgemeinen Konstruktor zu betrachten. In Bezug auf \ __ new__ scheint es ein bisschen anders zu sein, also werde ich als nächstes ein bisschen mehr schreiben.
Schreiben wir zunächst einen einfachen Code.
class sampleCls(object):
abc = 111
print "chkpnt10"
def __new__(cls):
cls.efg = 777
print "chkpnt20"
return super(sampleCls, cls).__new__(cls)
def __init__(self):
self.hij = 999
print "chkpnt30"
pprint(dir(sampleCls))
Wenn Sie dies tun,
chkpnt10
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'abc']
chkpnt10 wird ausgegeben, aber chkpnt20 und chkpnt30 werden nicht angezeigt. Weder efg noch hij sind im Klassenobjekt-Dump enthalten. Was passiert, wenn Sie eine Instanz erstellen?
class sampleCls(object):
abc = 111
print "chkpnt10"
def __new__(cls):
cls.efg = 777
print "chkpnt20"
return super(sampleCls, cls).__new__(cls)
def __init__(self):
self.hij = 999
print "chkpnt30"
i = sampleCls()
pprint (inspect.getmembers(sampleCls))
pprint (inspect.getmembers(i))
chkpnt10
chkpnt20
chkpnt30
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'abc',
'efg']
['__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'abc',
'efg',
'hij']
Es wird in der Reihenfolge chkpnt10, chkpnt20, chkpnt30 ausgegeben (der Code wird ausgeführt).
Das Klassenobjekt enthält abc und efg, jedoch nicht hij. Das Instanzobjekt enthält alle abc, evg und hij.
Das erste Argument von \ __ new__ ist ein Klassenobjekt, und im obigen Code wird efg festgelegt, sodass dem Klassenobjekt als Ergebnis efg hinzugefügt wird.
Mit super (sampleCls, cls) .__ new __ (cls)
wird aus dem Klassenobjekt ein Instanzobjekt erstellt und als Rückgabewert zurückgegeben.
Der Rückgabewert von \ __ new__ sollte ein Instanzobjekt dieser Klasse sein. Wenn der Rückgabewert etwas anderes ist, erstellt das Klassenobjekt kein Instanzobjekt.
init wird mit dem von \ __ new__ erstellten Instanzobjekt als erstem Argument aufgerufen.
\ New dient also zum Erstellen eines Instanzobjekts aus einem Klassenobjekt.
Wie im obigen Code können Sie durch Überschreiben von \ __ new__ das Klassenobjekt ändern, aus dem das Instanzobjekt erstellt wird. Diese Änderung wird auch im generierten Instanzobjekt berücksichtigt.
Aus dem oben Gesagten dachte ich, dass \ __ new__ kein Konstruktor ist.
Übrigens in der Klasse, ・ Geben Sie (neue Stilklasse) und ein ・ Klassenobjekt (alte Klasse) Das obige Beispiel ist eine neue Stilklasse. Es scheint.
Da ich Python verwende, das bei der Installation von DataNitro standardmäßig installiert wird, ist das oben Gesagte das in 2.7 ausgeführte. In 2.7 müssen Sie ein Objekt oder etwas erben, um New aufzurufen (überschrieben?). [* 2](# 2) </ sub> [* 3](# 3) </ sub> (Seit 3.0 oder höher wird das Objekt standardmäßig vererbt, sodass die Vererbung der Klasse nicht mehr angegeben werden muss.)
Ich habe in den letzten Tagen nach Python gesucht, und es gibt einen Mechanismus, mit dem ich es mit einem Programm ziemlich fein steuern kann. Selbst wenn ich mich auf die Klasse konzentriere, habe ich immer noch das Gefühl, dass etwas verschwommen ist. Sie können nacheinander überprüfen ... Aber ich hasse es nicht. Wenn Sie es tun, können Sie auf gute Weise süchtig danach sein.
Abgesehen davon gab es seit 3.0 Änderungen, die sich auf die Implementierungsebene auswirken, z. B. das Ändern von Anweisungen zu Ausdrücken und das Hinzufügen von Klammern. Es scheint, dass sich auch die Schnittstelle der Bibliothek geändert hat.
Ich frage mich, ob ich noch eine Weile Python studieren werde.
* 1. Vielleicht haben einige Bücher init als Konstruktor. Eher mehr? * 2. Ich versuche, den Kausalzusammenhang zwischen dem Erben des Objekts und dem Aufruf von \ __ new__ herauszufinden, und ich frage mich, ob der Attributwert den Aufruf von \ __ new__ steuert. Ich habe es nachgeschlagen, aber ich konnte es nicht finden. * 3. Auch wenn der Typ vererbt wird, wird \ __ new__ aufgerufen. In diesem Fall kann die Bedeutung jedoch aufgrund der Beziehung zur Metaklasse geringfügig abweichen. Zukünftige Forschungsfragen zum Typ.
Recommended Posts