Ich habe versucht, einen Wert in einem Klassenkonstruktor ( init ) zurückzugeben:
%Vor%Es gibt jedoch einen Laufzeitfehler, der besagt, dass init None zurückgeben soll. Wenn dies der Fall ist, wie zu verstehen:
%Vor%wo "a" als die Klasseninstanz zugewiesen wird?
Genau genommen ist es nicht A.__new__()
, das die Instanz a
erstellt.
Wenn Sie auch class A(object):
(oder class A:
definieren, wenn Sie Python3 verwenden, ist class A:
das alten Stil Klasse, die veraltet ist ), ist es __new__
von der geerbten object.__new__()
, die zum Erstellen der aufgerufen wird Instanz a
.
Wenn a = A()
ausgeführt wird, geschieht Folgendes:
A()
ist eine Abkürzung für A.__call__
object.__new__(cls, *args, **kwargs)
wo cls=A
, was passiert eigentlich unter Haube, um die Instanz a
zu erstellen. Er weist den Speicher für das neue Objekt zu und sollte dann ein neues Objekt (die Instanz) zurückgeben. __init__(self)
dann mit dem neu erzeugten Objekt aufgerufen, das an es übergeben wird, um das Objekt "zu initialisieren". Betrachten Sie die folgende Demo:
Wenn wir __new__
überschreiben und kein Objekt mehr zurückgeben, wird __init__
nicht angerufen werden:
Geben Sie jetzt eine neue Instanz mit object.__new__
zurück, und Sie werden das sehen
nach __new__
, __init__
würde auch aufgerufen:
Hier ist eine weitere Demo, um die Unterschiede anzuzeigen. Beachten Sie, dass die Instanz a
ohne Aufruf von __init__()
:
Grob gesagt gibt es zwei Möglichkeiten, neue Objekte in Python zu erstellen:
class
statements weist Python an, ein neues type / class Objekt zu erstellen (by
Unterklasse einer vorhandenen type / Klasse wie object
):
Tatsächlich haben alle Klassen / Typ Objekte den Typ type
. Der Typ von type
( type(type)
) ist immer noch Typ.
Sie können ein Objekt type / class ableiten.
Sie können auch ein neues Objekt erstellen, indem Sie ein vorhandenes Objekt type einfügen.
Dies geschieht über den Operator __call__
(Kürzel by ()
):
Unterklasse eines Instanzobjekts nicht möglich.
(Beachten Sie, dass Sie ein neues -Instanz -Objekt auch auf andere Weise erstellen können, z
da er den Listenoperator [1,2,3]
verwendet, erstellt er in diesem Fall eine Listeninstanz)
Sie können den Typ eines Objekts anhand von type(my_obj)
oder my_object.__class__
überprüfen.
Tatsächlich werden diese Objekte auch durch Instanziierung erzeugt, obwohl es a etwas andere Art von Instanziierung von dem, was zuvor erwähnt wurde.
Neben class
statement können Sie auch verwenden
type(cls_name, parent_class_tuple, attr_dict)
, um eine neue Klasse zu erstellen.
Zum Beispiel:
erstellt die Hello
-Klasse wie zuvor gezeigt.
Was ist type
? Geben Sie metaclass ein.
type
ist eine Metaklasse , die die Klasse der Klasse ist, d. h. Klassen sind
Instanzen von Metaklassen. Das __class__
von type
ist immer noch type
.
Hier ist ein Graph, der die Beziehungen zwischen Metaklasse , Klasse , Instanz :
%Vor% Wenn die Metaklasse type
aufgerufen wird, um eine neue Klasse zu erstellen, geht der ähnliche Ablauf:
type.__call__()
wird ausgeführt type.__new__()
weist Speicher zu und gibt dann eine neue Klasse (ein Metaklassen-Objekt) zurück und ruft dann type.__init__()
. type.__init__()
initialisiert die neu erstellte Klasse, die von Schritt 2 übergeben wurde. Sie können sogar eine neue Metaklasse erstellen, indem Sie type
:
Dann können Sie eine neue Klasse aus dieser MyMeta
metaclass erstellen, genau wie Sie
mit type
:
Oder verwenden Sie __metaclass__
bei der Definition Ihrer Klasse, die genau das hat
gleicher Effekt wie oben gezeigt:
Es funktioniert so:
Sie tun:
%Vor% A.__new__()
wird aufgerufen und gibt eine Instanz der Klasse A
zurück.
Äquivalent:
%Vor%Python ruft dann
auf %Vor%Welche, wie die Fehlermeldung sagt, sollte keinen Wert zurückgeben.
Wie Sie wissen, ist alles in Python ein Objekt und Klassen sind keine Ausnahme. Die Klasse A
ist ein Objekt mit einer Methode __call__(...)
, mit der Sie Dinge wie a = A()
schreiben können. Unter der Haube erstellt A.__call__
zuerst ein Objekt mit einer statischen Methode __new__
(die eine sinnvolle Standardimplementierung hat) und ruft dann das __init__
des neuen Objekts mit den richtigen Konstruktorargumenten auf.
Die Anforderung, dass __init__
None
zurückgeben soll, ist eine bewusste Implementierungsauswahl, mit der Sie sich darauf verlassen können, dass das Objekt vom Typ class ein Objekt konsistent zurückgibt
vom Typ Instanz der Klasse. Es ist das gleiche in vielen anderen Sprachen wie C ++.
Wenn es anders implementiert wird, würde es nutzlose Verwirrung schaffen.
Tags und Links python