mixins

Qu'est-ce que les mixins en python ?

Qu'est-ce qu'un mixin ?

Les mixins en Python sont des classes spéciales conçues pour offrir des fonctionnalités supplémentaires à d'autres classes via l'héritage, sans pour autant être destinées à être instanciées toutes seules.

On pourrait parler de boîte à outils que l'on greffe sur une classe pour lui donner de nouvelles fonctionnalités. Les mixins exploitent l'héritage multiple pour favoriser la réutilisabilité du code et respecter le principe DRY (Don't Repeat Yourself).

Pourquoi utiliser les mixins ?

Dans un héritage classique (où une classe Nain hérite de Personnage), on a une relation stricte qui dit que la classe Nain est un Personnage. Ce n'est pas le cas d'un mixin : la relation entre un mixin et une classe principale est plutôt du type "est capable de".

  • Modularité : Combiner plusieurs mixins pour créer des classes complexes

  • Lisibilité : Le code est mieux organisé et chaque mixin a une responsabilité unique

  • Éviter la duplication : Une même fonctionnalité peut être partagée entre les classes même si elles n'ont pas de lien de parenté direct

Exemple d'utilisation

Imaginons que nous ayons plusieurs classes dans notre application et que nous souhaitions leur ajouter des fonctionnalités : 

  • La conversion en JSON

  • Un affichage clair pour le débogage

Vous imaginez bien qu'au lieu de créer des méthodes dans chaque classe, nous allons créer deux mixins.

import json

# 1. Les deux Mixins
class JsonMixin:
    """Un mixin qui ajoute la capacité de se convertir en JSON."""
    def to_json(self):
        return json.dumps(self.__dict__, ensure_ascii=False)

class ReprMixin:
    """Un mixin qui améliore l'affichage d'un objet en mode debug."""
    def __repr__(self):
        attrs = ", ".join(f"{k}={v!r}" for k, v in self.__dict__.items())
        # !r permet d'obtenir une représentation de l'attribut qui est plus lisible (par exemple, les chaînes de caractères seront entourées de guillemets)
        return f"{self.__class__.__name__}({attrs})"

# 2. On combine les deux
class Utilisateur(JsonMixin, ReprMixin):
    def __init__(self, nom, email):
        self.nom = nom
        self.email = email

class Produit(JsonMixin, ReprMixin):
    def __init__(self, reference, prix):
        self.reference = reference
        self.prix = prix

# 3. Utilisation
user = Utilisateur("Patrick", "[email protected]")
print(user)          
# Affiche : Utilisateur(nom='Patrick', email='[email protected]')

print(user.to_json()) 
# Affiche : {"nom": "Patrick", "email": "[email protected]"}

article = Produit("PC-123", 999.99)
print(article)          
# Affiche : Produit(reference='PC-123', prix=999.99)

print(article.to_json()) 
# Affiche : {"reference": "PC-123", "prix": 999.99}
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

Les deux classes Utilisateur et Produit héritent de la capacité à se sérialiser en JSON et à s'afficher proprement pour le débogage.

À noter

Vous remarquerez que, par convention, un nom de mixin se termine par... Mixin !

Attention

En général, on évite de définir une méthode __init__ pour ne pas interférer avec la classe principale. Le mixin apporte ses méthodes, et la classe principale gère son propre état. Le mixin va uniquement consommer des attributs existants.

Point d'attention du MRO

Lorsque vous utilisez plusieurs mixins, vous faites ce que l'on appelle de l'héritage multiple. L'ordre dans lequel vous déclarez les classes parentes est crucial en raison du MRO (Method Resolution Order).

Python cherche les méthodes en lisant les classes de la gauche vers la droite. Si deux classes possèdent une méthode avec le même nom, c'est celle de la première classe rencontrée qui sera exécutée.

class TerminatorMixin:
    def phrase_culte(self):
        return "Hasta la vista, baby !"

class HumainMixin:
    def phrase_culte(self):
        return "Viens avec moi si tu veux vivre !"

# TerminatorMixin est placé en premier (à gauche)
class CyborgInfiltre(TerminatorMixin, HumainMixin):
    pass

# HumainMixin est placé en premier (à gauche)
class HumainDeguisement(HumainMixin, TerminatorMixin):
    pass

patrick = CyborgInfiltre()
print(patrick.phrase_culte()) 
# Affiche : Hasta la vista, baby !

sebastien = HumainDeguisement()
print(sebastien.phrase_culte()) 
# Affiche : Viens avec moi si tu veux vivre !
PYTHON
Un instant

Créez un compte pour exécuter ce code

Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.

Bravo, tu es prêt à passer à la suite

Rechercher sur le site

Inscris-toi à Docstring

Pour commencer ton apprentissage.

Tu as déjà un compte ? Connecte-toi.