In einem kürzlichen Projekt versuche ich etwas Ähnliches (komplexer, aber das gleiche Ergebnis):
%Vor%Ich verstehe das:
%Vor%Werden Klassenattribute nicht vererbt? Wenn ja, gibt es eine mögliche Lösung in einem ähnlichen Rahmen wie oben?
BEARBEITEN: Vielleicht ist es einfacher zu sehen, was ich meine, indem ich ein aktuelles (vereinfachtes) Beispiel aus dem Programm verwende.
%Vor%Im Grunde genommen möchten Sie eine Funktion auf der Grundfarbe ausführen, um eine dunklere Farbe zu erzeugen, die in der Klasse gespeichert wird (mehrere Instanzen der Klasse wollen die gleiche Farbe, aber es wird eine längere Klassenhierarchie geben). Ich hoffe, das wird mehr Sinn machen.
Es soll diese nicht erben. Die Metaklasse empfängt die Attribute, die für die Klasse definiert sind, die sie instanziiert, nicht die ihrer Basisklassen. Der Hauptpunkt des Metaklassenkonstruktors besteht darin, Zugriff auf das zu bekommen, was tatsächlich im Klassenkörper angegeben ist.
Tatsächlich sind die Attribute der Basisklasse überhaupt nicht "in" der Unterklasse. Es ist nicht so, dass sie in die Unterklasse "kopiert" werden, wenn Sie sie definieren, und tatsächlich "weiß" die Unterklasse zur Erstellungszeit nicht einmal, welche Attribute ihre Oberklassen haben könnten. Wenn Sie auf B.foo
zugreifen, versucht Python zuerst, das Attribut auf B zu finden. Wenn es nicht gefunden wird, sucht Python nach seinen Superklassen. Dies geschieht jedes Mal dynamisch, wenn Sie versuchen, ein solches Attribut zu lesen. Der Metaklassen-Mechanismus soll keinen Zugriff auf Attribute der Oberklasse haben, da diese in der Unterklasse nicht vorhanden sind.
Ein möglicherweise damit verbundenes Problem ist, dass Ihre Definition von __new__
falsch ist. Die Argumente für die Metaklasse __new__
sind cls, name, bases und attrs. Das dritte Argument ist die Liste der Basisklassen, nicht "Argumente" (was auch immer Sie beabsichtigen). Das vierte Argument ist die Liste der Attribute, die im Klassenkörper definiert sind. Wenn Sie Zugriff auf geerbte Attribute haben möchten, können Sie diese über die Basen abrufen.
Wie auch immer, was versuchst du mit diesem Schema zu erreichen? Es gibt wahrscheinlich einen besseren Weg, es zu tun.
Wenn Sie __init__
anstelle von __new__
verwenden, können Sie die Attribute der Basisklasse erben:
Wenn A erstellt wird, wird Folgendes zurückgegeben:
%Vor%Wenn B erstellt wird, wird Folgendes zurückgegeben:
%Vor% Beachten Sie, und das hat @BrenBarn in seiner Antwort gesagt, dass foo
nicht in% co_de ist % wenn attr
erstellt wird. Deshalb löst der Code in der OP-Frage KeyError aus. Aufruf von B
sucht jedoch nach self.foo
in foo
. Wenn es nicht gefunden werden kann, sucht es in seinen Basen nach IE B
.
Die Metaklasse für beide Klassen kann durch Betrachten ihrer Klasse bestimmt werden:
%Vor% Die Tatsache, dass die metaclass A
-Methode aufgerufen wird, wenn __init__
zugewiesen und initialisiert wird, zeigt, dass B
und self.foo
in attr
ebenfalls beweist, dass stdout
's Meta-Klasse B
.
Tags und Links python metaclass class-attributes