logo oujood
🔍

La fonction super() en Python : héritage et classes parentes

Comment déléguer l'initialisation et étendre les méthodes héritées avec super() — de l'héritage simple au MRO.

OUJOOD.COM

En Python, quand une classe hérite d'une autre, elle a besoin d'appeler le code de sa classe parente sans le réécrire. super() remplit ce rôle. Cette fonction intégrée donne accès aux méthodes et attributs de la classe parente depuis une classe enfant. On l'utilise surtout dans les constructeurs pour initialiser les attributs hérités, mais aussi pour étendre n'importe quelle méthode sans dupliquer son code.

Étape 1 — Définir la classe parente

Avant d'utiliser super(), il faut une classe parente à appeler. On crée ici une classe Personne avec un constructeur qui reçoit un nom et un âge, et une méthode d'affichage.

  📋 Copier le code

class Personne:
    # Le constructeur reçoit un nom et un âge
    def __init__(self, nom, age):
        self.nom = nom
        self.age = age

    # Méthode pour afficher les informations
    def afficher_infos(self):
        print(f"Nom : {self.nom}, Age : {self.age}")

# Test de la classe parente seule
personne1 = Personne("Alice", 30)
personne1.afficher_infos()

Résultat attendu :

Nom : Alice, Age : 30

La classe Personne stocke deux informations : le nom et l'âge. C'est cette base qu'on va réutiliser dans la classe enfant via super() — sans la réécrire.

Étape 2 — Appeler le constructeur parent avec super().__init__()

La classe Etudiant hérite de Personne. Elle a besoin des mêmes attributs (nom, age) plus un attribut supplémentaire (niveau). Au lieu de réécrire l'initialisation de nom et age, on appelle super().__init__() pour confier ce travail au constructeur parent. On n'initialise manuellement que ce qui est nouveau.

  📋 Copier le code

class Etudiant(Personne):
    def __init__(self, nom, age, niveau):
        # super().__init__() appelle le constructeur de Personne
        # Il s'occupe de self.nom et self.age
        super().__init__(nom, age)
        # On ajoute uniquement ce qui est propre à Etudiant
        self.niveau = niveau

    def afficher_infos(self):
        # On réutilise l'affichage de Personne...
        super().afficher_infos()
        # ...puis on ajoute la ligne spécifique à l'étudiant
        print(f"Niveau : {self.niveau}")

etudiant1 = Etudiant("Bob", 20, "Bac+2")
etudiant1.afficher_infos()

Résultat attendu :

Nom : Bob, Age : 20
Niveau : Bac+2

Deux utilisations de super() ici. Dans le constructeur, super().__init__(nom, age) délègue l'initialisation des attributs hérités. Dans afficher_infos(), super().afficher_infos() exécute la version parente avant d'ajouter la ligne du niveau. Python exécute les deux à la suite, sans qu'on ait rien réécrit de la classe parente.

⚠ Si vous oubliez super().__init__(nom, age) et essayez d'accéder à self.nom, Python lève une AttributeError : les attributs hérités ne sont définis que si le constructeur parent est appelé.

Étape 3 — Étendre une méthode sans la remplacer

super() ne sert pas qu'aux constructeurs. On peut l'utiliser pour enrichir n'importe quelle méthode héritée. Sans super().manger(), la méthode parente serait silencieusement écrasée — avec, on la conserve et on la complète.

  📋 Copier le code

class Animal:
    def manger(self):
        print("L'animal mange.")

class Chien(Animal):
    def manger(self):
        # On appelle d'abord la version générale d'Animal
        super().manger()
        # Puis on ajoute le comportement propre au chien
        print("Le chien mange des croquettes et aboie.")

rex = Chien()
rex.manger()

Résultat attendu :

L'animal mange.
Le chien mange des croquettes et aboie.

Étape 4 — Héritage de constructeur avec des attributs spécifiques

La classe Voiture hérite de Vehicule et ajoute un modèle. super().__init__() prend en charge les attributs partagés ; on n'initialise manuellement que ceux qui sont nouveaux. Si le constructeur de Vehicule évolue un jour, Voiture en hérite sans modification supplémentaire.

  📋 Copier le code

class Vehicule:
    def __init__(self, marque, annee):
        self.marque = marque
        self.annee = annee

class Voiture(Vehicule):
    def __init__(self, marque, annee, modele):
        # marque et annee sont gérés par le constructeur de Vehicule
        super().__init__(marque, annee)
        # modele est propre à Voiture
        self.modele = modele

    def afficher(self):
        print(f"{self.marque} {self.modele} ({self.annee})")

v = Voiture("Renault", 2022, "Clio")
v.afficher()

Résultat attendu :

Renault Clio (2022)

Étape 5 — Héritage multiple et MRO : quel parent super() appelle-t-il ?

Python accepte qu'une classe hérite de plusieurs parents. Dans ce cas, super() ne choisit pas au hasard : il suit le MRO (Method Resolution Order), un ordre calculé automatiquement par Python à la création de la classe selon l'algorithme C3. L'ordre dans lequel vous listez les parents dans la définition de la classe détermine cet ordre.

  📋 Copier le code

class Volant:
    def se_deplacer(self):
        print("Je vole dans les airs.")

class Nageant:
    def se_deplacer(self):
        print("Je nage dans l'eau.")

# Canard hérite de Volant en premier, puis de Nageant
class Canard(Volant, Nageant):
    def se_deplacer(self):
        # super() appelle Volant.se_deplacer() en suivant le MRO
        super().se_deplacer()
        print("Je peux aussi marcher.")

canard = Canard()
canard.se_deplacer()

# Pour consulter l'ordre de résolution :
print(Canard.__mro__)

Résultat attendu :

Je vole dans les airs.
Je peux aussi marcher.
(<class '__main__.Canard'>, <class '__main__.Volant'>, <class '__main__.Nageant'>, <class 'object'>)

Canard hérite de Volant avant Nageant — c'est donc Volant.se_deplacer() que super() appelle. Avec class Canard(Nageant, Volant), l'ordre s'inverserait et c'est "Je nage dans l'eau." qui s'afficherait. L'héritage multiple demande une attention particulière à l'ordre des classes dans la définition.

Récapitulatif : les usages de super() en un seul script

Ce script rassemble tous les cas vus dans ce tutoriel. Copiez-le et exécutez-le tel quel pour vérifier chaque comportement.

  📋 Copier le code

# --- Héritage simple : super().__init__() ---
class Personne:
    def __init__(self, nom, age):
        self.nom = nom
        self.age = age
    def afficher_infos(self):
        print(f"Nom : {self.nom}, Age : {self.age}")

class Etudiant(Personne):
    def __init__(self, nom, age, niveau):
        super().__init__(nom, age)
        self.niveau = niveau
    def afficher_infos(self):
        super().afficher_infos()
        print(f"Niveau : {self.niveau}")

etudiant1 = Etudiant("Bob", 20, "Bac+2")
etudiant1.afficher_infos()
# Nom : Bob, Age : 20
# Niveau : Bac+2

# --- Extension de méthode ---
class Animal:
    def manger(self):
        print("L'animal mange.")

class Chien(Animal):
    def manger(self):
        super().manger()
        print("Le chien mange des croquettes et aboie.")

Chien().manger()
# L'animal mange.
# Le chien mange des croquettes et aboie.

# --- Héritage multiple + MRO ---
class Volant:
    def se_deplacer(self):
        print("Je vole dans les airs.")

class Nageant:
    def se_deplacer(self):
        print("Je nage dans l'eau.")

class Canard(Volant, Nageant):
    def se_deplacer(self):
        super().se_deplacer()
        print("Je peux aussi marcher.")

Canard().se_deplacer()
# Je vole dans les airs.
# Je peux aussi marcher.

Par carabde | Mis à jour le 9 juin 2026