Les classes (par défaut) sont des instances de type
. Tout comme une instance d'une classe Foo
est créé par foo = Foo(...)
, une instance de type
(c'est-à-dire une classe) est créé par myclass = type(name, bases, clsdict)
.
Si vous voulez que quelque chose de spécial se produise au moment de la création de la classe, alors vous devez modifier la chose qui crée la classe -- c'est à dire type
. La façon de procéder est de définir une sous-classe de type
-- c'est-à-dire une métaclasse.
Une métaclasse est à sa classe ce qu'une classe est à son instance.
En Python2, vous définiriez la métaclasse d'une classe avec
class SuperClass:
__metaclass__ = Watcher
donde Watcher
est une sous-classe de type
.
Dans Python3, la syntaxe a été modifiée comme suit
class SuperClass(metaclass=Watcher)
Les deux sont équivalents à
Superclass = Watcher(name, bases, clsdict)
où dans ce cas, name
est égal à la chaîne de caractères 'Superclass'
y bases
est le tuple (object, )
. Le site clsdict
est un dictionnaire des attributs de classe définis dans le corps de la définition de la classe.
Notez la similitude avec myclass = type(name, bases, clsdict)
.
Ainsi, de la même manière que vous utiliseriez la classe __init__
pour contrôler les événements au moment de la création d'une instance, vous pouvez contrôler les événements au moment de la création d'une classe à l'aide d'une métaclasse __init__
:
class Watcher(type):
def __init__(cls, name, bases, clsdict):
if len(cls.mro()) > 2:
print("was subclassed by " + name)
super(Watcher, cls).__init__(name, bases, clsdict)
class SuperClass:
__metaclass__ = Watcher
print("foo")
class SubClass0(SuperClass):
pass
print("bar")
class SubClass1(SuperClass):
print("test")
imprime
foo
was subclassed by SubClass0
bar
test
was subclassed by SubClass1