Accéder au contenu principal

Introduction aux métaclasses Python

Dans ce tutoriel, découvrez ce que sont les métaclasses, comment les implémenter en Python et comment en créer sur mesure.
Actualisé 19 sept. 2026  · 6 min lire

Explorer avec l’IA

ChatGPTClaudePerplexity

Une métaclasse en Python est une classe de classe qui définit le comportement d’une classe. Une classe est elle-même une instance d’une métaclasse. Une classe en Python définit comment se comporteront les instances de cette classe. Pour bien comprendre les métaclasses, il faut déjà être à l’aise avec les classes Python. Avant d’entrer dans le vif du sujet, clarifions quelques notions.

Tout est objet en Python

class TestClass():
    pass

my_test_class = TestClass()
print(my_test_class)
<__main__.TestClass object at 0x7f6fcc6bf908>

Les classes Python peuvent être créées dynamiquement

type en Python permet d’obtenir le type d’un objet. Vérifions le type de l’objet créé ci-dessus.

type(TestClass)
type
type(type)
type

Attendez, que s’est-il passé ? On s’attendrait à ce que le type de l’objet créé soit class, mais ce n’est pas le cas. Gardez cela en tête, nous y revenons plus loin. On remarque aussi que le type de type est type lui-même. C’est une instance de type. Autre particularité de type : il permet de créer des classes dynamiquement. Voyons comment faire. La classe DataCamp ci-dessous peut être créée avec type de la manière suivante :

class DataCamp():
    pass
DataCampClass = type('DataCamp', (), {})
print(DataCampClass)
print(DataCamp())
<class '__main__.DataCamp'>
<__main__.DataCamp object at 0x7f6fcc66e358>

Dans l’exemple ci-dessus, DataCamp est le nom de la classe tandis que DataCampClass est la variable qui référence la classe. Avec type, on peut passer des attributs de classe via un dictionnaire comme ci-dessous :

PythonClass = type('PythonClass', (), {'start_date': 'August 2018', 'instructor': 'John Doe'} )
print(PythonClass.start_date, PythonClass.instructor)
print(PythonClass)
August 2018 John Doe
<class '__main__.PythonClass'>

Si nous voulons que PythonClass hérite de la classe DataCamp, on la passe comme second argument lors de la définition avec type

PythonClass = type('PythonClass', (DataCamp,), {'start_date': 'August 2018', 'instructor': 'John Doe'} )
print(PythonClass)
<class '__main__.PythonClass'>

Maintenant que ces deux notions sont posées, on réalise que Python crée les classes à l’aide d’une métaclasse. Nous avons vu que tout est objet en Python ; ces objets sont créés par des métaclasses. Chaque fois que l’on utilise class pour définir une classe, une métaclasse fait la magie en coulisses. Nous avons déjà vu type le faire en pratique. C’est comparable à str qui crée des chaînes et à int qui crée des entiers. En Python, l’attribut ___class__ permet d’obtenir le type de l’instance courante. Créons une chaîne et vérifions son type.

article = 'metaclasses'
article.__class__
str

On peut également vérifier le type avec type(article).

type(article)
str

Si l’on vérifie le type de str, on constate aussi que c’est type.

type(str)
type

Si l’on vérifie le type de float, int, list, tuple et dict, on obtient le même résultat. Car tous ces objets sont de type type.

print(type(list),type(float), type(dict), type(tuple))
<class 'type'> <class 'type'> <class 'type'> <class 'type'>

Nous avons vu que type crée des classes. Donc, si l’on consulte le __class__ de __class__, cela devrait renvoyer type.

article.__class__.__class__
type

Maîtrisez vos compétences en matière de données avec DataCamp

Plus de 10 millions de personnes apprennent Python, R, SQL et d'autres compétences techniques grâce à nos cours pratiques élaborés par des experts du secteur.

Commencer À Apprendre
learner-on-couch@2x.jpg

Créer des métaclasses personnalisées

En Python, on peut personnaliser le processus de création d’une classe en passant le mot-clé metaclass dans la définition de la classe. On peut aussi l’obtenir par héritage si la classe parente définit déjà ce mot-clé.

class MyMeta(type):
    pass

class MyClass(metaclass=MyMeta):
    pass

class MySubclass(MyClass):
    pass

On voit ci-dessous que le type de la classe MyMeta est type et que le type de MyClass et MySubClass est MyMeta.

print(type(MyMeta))
print(type(MyClass))
print(type(MySubclass))
<class 'type'>
<class '__main__.MyMeta'>
<class '__main__.MyMeta'>

Lorsqu’aucune métaclasse n’est spécifiée lors de la définition d’une classe, la métaclasse par défaut type est utilisée. Si une métaclasse est fournie et qu’elle n’est pas une instance de type(), elle est utilisée directement comme métaclasse.

__new__ et __init__

On peut aussi définir des métaclasses de l’une des deux manières suivantes. Nous expliquons ensuite la différence.

class MetaOne(type):
    def __new__(cls, name, bases, dict):
        pass

class MetaTwo(type):
    def __init__(self, name, bases, dict):
        pass

__new__ s’utilise lorsqu’on veut définir le dict ou le tuple bases avant la création de la classe. La valeur de retour de __new__ est généralement une instance de cls. __new__ permet aux sous-classes de types immuables de personnaliser la création d’instances. Il peut être surchargé dans des métaclasses personnalisées pour adapter la création de classe. __init__ est en général appelé après la création de l’objet afin de l’initialiser.

Méthode __call__ de métaclasse

Selon la documentation officielle, on peut aussi surcharger d’autres méthodes de classe en définissant une méthode __call__() personnalisée dans la métaclasse afin d’introduire un comportement spécifique lors de l’appel de la classe.

Méthode __prepare__ de métaclasse

D’après le modèle de données Python

Une fois la métaclasse appropriée identifiée, l’espace de noms de la classe est préparé. Si la métaclasse possède un attribut __prepare__, il est appelé comme suit : namespace = metaclass.__prepare__(name, bases, **kwds) (les arguments nommés additionnels, le cas échéant, proviennent de la définition de la classe). Si la métaclasse n’a pas d’attribut __prepare__, l’espace de noms de la classe est initialisé comme un mapping ordonné vide. - docs.python.org

Conception d’un singleton avec une métaclasse

Il s’agit d’un patron de conception qui limite l’instanciation d’une classe à un seul objet. Cela peut être utile, par exemple, pour une classe de connexion à une base de données, où l’on souhaite n’avoir qu’une seule instance de la connexion.

class SingletonMeta(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(SingletonMeta,cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class SingletonClass(metaclass=SingletonMeta):
    pass

Conclusion

Dans cet article, nous avons vu ce que sont les métaclasses et comment les implémenter dans nos programmes Python. Les métaclasses peuvent servir, entre autres, à la journalisation, à l’enregistrement des classes à la création ou encore au profilage. Le concept peut sembler assez abstrait et vous vous demandez peut-être si vous en avez réellement besoin. Le vétéran de Python, Tim Peters, y répond mieux que quiconque.

"Les métaclasses relèvent d’une magie plus profonde que ce dont 99 % des utilisateurs devraient se préoccuper. Si vous vous demandez si vous en avez besoin, la réponse est non (ceux qui en ont vraiment besoin le savent avec certitude et n’ont pas besoin d’une explication du pourquoi)." - realpython

Pour aller plus loin en Python, commencez le parcours de compétences Python Programming sur DataCamp et consultez notre tutoriel sur les classes Python.

Références

Lien un

Lien deux

Sujets
Python

Cours Python

Cours

Introduction à Python

4 h
7M
Apprenez les bases de l’analyse de données avec Python en quatre heures et explorez ses principaux packages.
Afficher les détailsRight Arrow
Commencer Le Cours
Voir plusRight Arrow