Die Python 3 Dokumentation beschreibt deutlich, wie die Metaklasse von a Klasse ist festgelegt:
- Wenn keine Basen und keine explizite Metaklasse angegeben sind, wird type () verwendet
- Wenn eine explizite Metaklasse angegeben wird und es sich nicht um eine Instanz von type () handelt, wird sie direkt als Metaklasse
verwendet- Wenn eine Instanz von type () als explizite Metaklasse angegeben wird oder Basen definiert sind, wird die am weitesten abgeleitete Metaklasse
verwendet
Daher ist es gemäß der zweiten Regel möglich, eine Metaklasse anzugeben, die eine aufrufbare Funktion verwendet. Z. B.
%Vor% Ist die Metaklasse von MyClass
: metaclass_callable
oder MyMetaclass
? Die zweite Regel in der Dokumentation besagt, dass das bereitgestellte Callable "direkt als Metaklasse verwendet wird". Es scheint jedoch sinnvoller zu sein, dass die Metaklasse MyMetaclass
seit
MyClass
und MyDerived
haben den Typ MyMetaclass
, metaclass_callable
wird einmal aufgerufen und scheint dann nicht wiederherstellbar zu sein, metaclass_callable
in keiner Weise (sie verwenden MyMetaclass
). Gibt es irgendetwas, was Sie mit einer Callable tun können, die Sie mit einer Instanz von type
nicht tun können? Was ist der Zweck, eine willkürliche Callable zu akzeptieren?
In Bezug auf Ihre erste Frage sollte die Metaklasse MyMetaclass
sein (was es ist):
Der Grund ist, dass, wenn die Metaklasse keine Instanz des Typs python ist, die Methaklasse aufgerufen wird, indem diese Argumente an name, bases, ns, **kwds
übergeben werden (siehe new_class
) und da Sie Ihre echte Metaklasse in dieser Funktion zurückgeben, wird sie korrekt Geben Sie für Metaklasse ein.
Und über die zweite Frage:
Was ist der Zweck der Annahme einer willkürlichen aufrufbar?
Es gibt keinen speziellen Zweck, ist eigentlich die Art von Metaklassen , denn wenn eine Instanz einer Klasse aufgerufen wird, ruft sie immer die Metaklasse auf, indem sie ihre __call__
-Methode aufruft:
Das bedeutet, dass Sie alle aufrufbaren Nachrichten als Ihre Metaklasse weitergeben können. Wenn Sie es zum Beispiel mit einer verschachtelten Funktion testen, ist das Ergebnis immer noch dasselbe:
%Vor%Für weitere Informationen hier ist, wie Python eine Klasse kiste:
Er ruft die Funktion new_class
auf, die prepare_class
in sich selbst aufruft, und dann, wie Sie im prepare_class
python sehen können, ruft sie die Methode __prepare__
der entsprechenden Metaklasse auf. co_de% function) und den entsprechenden Namespace für die Klasse erstellen.
Also hier ist die Hierarchie der Ausführung der Metakalss Methoden:
_calculate_meta
1
__prepare__
__call__
__new__
Und hier ist der Quellcode:
%Vor%1. Beachten Sie, dass es implizit innerhalb der new_class -Funktion und vor der Rückgabe aufgerufen wird.
Nun, die type
ist natürlich MyMetaClass
. metaclass_callable
wird anfänglich als Metaklasse ausgewählt, da in metaclass
angegeben wurde. kwarg und als solches wird __call__
(ein einfacher Funktionsaufruf) ausgeführt.
Es wird einfach so aufgerufen, dass% ce_de% aufgerufen wird und dann print
aufgerufen wird (was MyMetaClass.__call__
aufruft, da type.__call__
nicht für __call__
überschrieben wurde). Dort wird die Zuweisung von MyMetaClass
vorgenommen zu cls.__class__
.
MyMetaClass
wird einmal aufgerufen und scheint dann nicht wiederherstellbar zu sein
Ja, es wird nur anfänglich aufgerufen und steuert dann die Kontrolle über metaclass_callable
. Ich kenne keine Klassenattribute, die diese Informationen enthalten.
abgeleitete Klassen verwenden (so weit ich das beurteilen kann)
MyMetaClass
in keiner Weise.
Nein, wenn kein metaclass_callable
explizit definiert ist, die beste Übereinstimmung für die Metaklassen von metaclass
(hier bases
) wird verwendet (resultierend in MyClass
).
Wie bei der Frage MyMetaClass
ist es ziemlich sicher, dass alles, was Sie mit einer aufrufbaren Funktion tun können, auch möglich ist, indem Sie eine Instanz von type mit 2
entsprechend überschreiben. Was why betrifft, möchten Sie vielleicht nicht die vollständige Klassenerstellung durchführen, wenn Sie nur geringfügige Änderungen vornehmen möchten, wenn Sie tatsächlich eine Klasse erstellen.
Was Frage 1 angeht, denke ich, dass die "Metaklasse" einer Klasse cls
als type(cls)
verstanden werden sollte. Diese Art zu verstehen ist kompatibel mit Pythons Fehlermeldung im folgenden Beispiel:
Das heißt, entsprechend der Fehlermeldung ist die Metaklasse einer Klasse eine Klasse, obwohl die zur Konstruktion der Klasse verwendete Callable einfach alles sein kann.
In Bezug auf die zweite Frage, in der Tat mit einer Unterklasse des Typs, der als Metaklasse verwendet wird, können Sie das gleiche wie bei jeder anderen aufrufbaren Funktion tun. Insbesondere ist es möglich, dass es etwas ergibt, das nicht seine Instanz ist:
%Vor%Warum Python die Freiheit bietet, irgendwelche Calls zu benutzen: Das vorherige Beispiel zeigt, dass es eigentlich egal ist, ob das Callable ein Typ ist oder nicht.
Übrigens, hier ist ein lustiges Beispiel: Es ist möglich, Metaklassen zu programmieren, die selbst eine Metaklasse haben, die sich von type
unterscheidet - nennen wir es eine Metamethaklasse. Die metametaclass implementiert, was passiert, wenn eine Metaklasse aufgerufen wird. Auf diese Weise ist es möglich, eine Klasse mit zwei Basen zu erstellen, deren Metaklassen nicht Unterklassen voneinander sind (vergleiche mit Pythons Fehlermeldung im obigen Beispiel!). Tatsächlich ist nur die Metaklasse der resultierenden Klasse eine Unterklasse der Metaklasse der Basen, und diese Metaklasse wird im Handumdrehen erzeugt:
Was weniger Spaß macht: Das vorhergehende Beispiel wird in Python 3 nicht funktionieren. Wenn ich richtig verstehe, erstellt Python 2 die Klasse und überprüft, ob ihre Metaklasse eine Unterklasse aller ihrer Basen ist, während Python 3 zuerst
Bearbeiten : Die neue Frage lautet hier
Tags und Links python class python-3.x metaclass