Die Klasse hat kein __metaclass__
Attribut gesetzt ... weil Sie es nie gesetzt haben!
Welche Metaklasse wird normalerweise verwendet von ein Name __metaclass__
in einem Klassenblock festgelegt. Das __metaclass__
Attribut wird nicht von der Metaklasse festgelegt. Wenn Sie also direkt eine Metaklasse aufrufen und nicht __metaclass__
setzen und es Python überlassen, es herauszufinden, wird kein Attribut __metaclass__
gesetzt.
In der Tat sind normale Klassen alle Instanzen der Metaklasse type
, also wenn die Metaklasse immer das __metaclass__
Attribut auf seinen Instanzen gesetzt dann jede Klasse würde ein __metaclass__
Attribut (die meisten von ihnen auf type
).
Ich würde nicht Ihre Dekorateur Ansatz verwenden. Es verdunkelt die Tatsache, dass eine Metaklasse involviert ist (und welche), ist immer noch eine Zeile von Boilerplate, und es ist einfach chaotisch eine Klasse aus den 3 definierenden Features von (name, bases, attributes)
zu erstellen, nur um diese 3 Bits aus der resultierenden Klasse herauszuziehen, Wirf die Klasse weg und mach aus diesen 3 Bits eine neue Klasse!
Wenn Sie dies tun in Python 2.x:
class A(object):
__metaclass__ = MyMeta
def __init__(self):
pass
Sie in etwa das gleiche Ergebnis erhalten würden, wenn Sie dies geschrieben hatte:
attrs = {}
attrs['__metaclass__'] = MyMeta
def __init__(self):
pass
attrs['__init__'] = __init__
A = attrs.get('__metaclass__', type)('A', (object,), attrs)
In Wirklichkeit die Metaklasse Berechnung ist mehr kompliziert, da es tatsächlich eine Suche durch alle Basen geben muss, um zu bestimmen, ob es einen Metaklassenkonflikt gibt, und wenn eine der Basen type
nicht als Metaklasse hat und attrs
keine __metaclass__
enthält, dann ist die Standardmetaklasse die Metaklasse des Vorfahren statt type
. Dies ist eine Situation, in der ich davon ausgehe, dass sich die "Lösung" Ihres Dekorateurs von der direkten Verwendung von __metaclass__
unterscheidet. Ich bin nicht sicher, was genau passieren würde, wenn Sie Ihren Dekorateur in einer Situation verwenden würden, in der die Verwendung von __metaclass__
Ihnen einen Metaklassenkonfliktfehler geben würde, aber ich würde nicht erwarten, dass es angenehm ist.
Wenn andere Metaklassen beteiligt sind, würde Ihre Methode dazu führen, dass sie zuerst ausgeführt werden (möglicherweise ändern, was der Name, die Basen und Attribute sind!) Und dann aus der Klasse herausziehen und daraus eine erstellen neue Klasse. Dies könnte möglicherweise ganz anders sein als das, was Sie mit __metaclass__
bekommen würden.
Wie für die __dict__
nicht geben Sie ein echtes Wörterbuch, das ist nur ein Implementierungsdetail; Ich würde aus Leistungsgründen raten. Ich bezweifle, gibt es eine Spezifikation, die besagt, dass die einer (Nicht-Klasse) Instanz muss der gleiche Typ sein wie die __dict__
einer Klasse (die auch eine Instanz BTW ist, nur eine Instanz einer Metaklasse). Das Attribut einer Klasse ist ein "dictproxy", mit dem Sie Attributschlüssel nachschlagen können, als wäre es ein dict
, aber immer noch kein dict
. type
ist wählerisch über den Typ seines dritten Arguments; es will ein echtes Diktat, nicht nur ein "dict-like" -Objekt (Schande über das verdorbene Tippen). Es ist keine 2.x vs 3.x Sache; Python 3 verhält sich auf die gleiche Art und Weise, obwohl es Ihnen eine schönere Zeichenfolgendarstellung des dictproxy
gibt. Python 2.4 (welches das älteste 2.x ist, das ich leicht verfügbar habe) hat auch dictproxy
Objekte für Klasse __dict__
Objekte.
Ich frage mich nur, ob es einen Dekorator gab, der dem Attribut '__metaclass__' in einer Klassendefinition entspricht. Ich glaube, ein anderer Teil meiner Frage ist, dass mein 'Dekorateur' * schien * zu arbeiten, aber ich bemerkte, dass die dekorierte Klasse kein '__metaclass__' Attribut hat, also gibt es einen klaren Unterschied zwischen den beiden Methoden; warum ist das? – Chris