Goswin hat geschrieben:(1) Wie unterscheide ich, ob ein Objekt X eine Metaklasse ist oder nicht?
Normalerweise wäre X von type abgeleitet, aber das muss es nicht. Wirklich wichtig ist, dass die "Metaklasse" mit drei Parametern (Name, Basisklassen, Classdict) aufgerufen werden kann. Damit es wenigstens etwas Sinn macht, sollte das zurückgegebene Objekt ebenfalls aufrufbar ("instanzierbar") sein. Wenn das der Fall ist, dann kann man dieses "Ding" ansatzweise wie eine Metaklasse benutzen.
Code: Alles auswählen
def foo(name, bases, attrs):
def bar():
return "FOOBAR"
return bar
class X(object):
__metaclass__ = foo
X
# <function bar at ...>
x = X()
x
# 'FOOBAR'
Damit es aber sinnvoll wird, sollte die Metaclasse von type erben und natürlich das Metaklassen-Protokoll implementieren. Dann kann man etwas Metamagic betreiben.
(2) Ist das "object", von dem alle anderen Klassen und sogar type erben (siehe type.__mro__), nun eine Metaklasse oder nicht?
Nein. Wenn sie es wäre, dann könnte man "__metaclass__ = object" schreiben. Aber das geht nicht, weil object keine Argumente akzeptiert.
type und object sind sehr speziell. Sie hängen voneinander ab. type ist eine Instanz von sich selbst und gleichzeitig eine Unterklasse von object. object hat keine Superklassen, ist aber eine Instanz von type (das eine Instanz von object ist). Ganz schön kompliziert. Ist aber völlig egal. Das hilft uns nicht wirklich weiter. Fakt ist: type ist eine Metaklasse, da deren Instanzen Klassen sind. object ist eine Instanz von type und dadurch eine Klasse und ist die superste Superklasse, die es in Python gibt
. (Ich red hier nur von new style classes.)
(3) Erben Metaklassen manchmal ausschließlich von gewöhnlichen Klassen (siehe type.__mro__)?
Ja, siehe type, welches von object erbt. Gut, es erbt auch von sich selbst. Aber schau mal:
Code: Alles auswählen
class NoType(object):
def __new__(metacls, name, bases, attrs):
return type(name, bases, attrs)
class X(object):
__metaclass__ = NoType
X
# <class '__main__.X'>
x = X()
x
# <__main__.X object at 0xb7d9228c>
Metaklassen müssen also nicht von type erben, um irgendwie als Metaklassen zu dienen. Aber wenn du Metaklassen mit all ihren Fähigkeiten nutzen willst, kommst du nicht umhin, von type zu erben. Oder in der "Metaklasse" eine Instanz einer Klasse, die von type erbt, zurückzugeben.
Gruß,
Manuel