Héritage

Construire une classe à partir d’une autre : la classe dérivée reprend les méthodes de la classe de base et peut les étendre ou les redéfinir.

Sur cette page

Exemple

#
Python
class User:
    def __init__(self, name):
        self.name = name

    def greet(self):
        return f"Salut, je suis {self.name}"

    def role(self):
        return "utilisateur"

class Mentor(User):
    def role(self):
        return "mentor"

    def review(self, task):
        return f"{self.name} corrige la tâche {task}"

darwin = Mentor("Darwin")
print(darwin.greet())
print(darwin.role())
print(darwin.review("7_3"))
print(isinstance(darwin, User), issubclass(Mentor, User))
Résultatrésultat enregistré, vous pouvez le vérifier
Salut, je suis Darwin
mentor
Darwin corrige la tâche 7_3
True True

Définition et utilisation

#

L’héritage permet de créer une nouvelle classe à partir d’une classe existante. Vous indiquez la classe de base entre parenthèses après le nom : class Mentor(User). La classe dérivée reçoit automatiquement toutes les méthodes et tous les attributs de la classe de base, donc vous n’y écrivez que ce qui est nouveau ou différent.

Une méthode portant le même nom dans la classe dérivée redéfinit la version de base. Python cherche une méthode d’abord dans la classe de l’objet, puis dans sa classe de base, et ainsi de suite, jusqu’à la classe intégrée object, dont hérite chaque classe. Cet ordre (MRO, pour method resolution order) est donné par l’attribut __mro__. Depuis une méthode redéfinie, vous appelez la version de base via super().

La fonction isinstance(objet, Classe) renvoie aussi True pour les objets des classes dérivées, tandis que issubclass(A, B) vérifie la relation entre les classes elles-mêmes. Grâce à cela, du code écrit pour la classe de base fonctionne avec chaque classe dérivée, et chacune peut répondre à sa façon au même appel. Ce phénomène s’appelle le polymorphisme.

Une classe peut hériter de plusieurs classes à la fois (class Quiz(Timed, Scored)), ce qui est utile pour de petites classes qui ajoutent chacune une seule capacité, les mixins. Utilisez l’héritage quand la relation « est un » s’applique : un mentor est un utilisateur. Quand un objet se contente « d’avoir » un autre objet, par exemple un cours a une liste de leçons, stockez-le comme attribut. Cette approche s’appelle la composition.

Syntaxe

#
Syntaxe
class Base:
    ...

class Dérivée(Base):
    ...

class Dérivée(Base1, Base2):
    ...

Plus d’exemples

#
Polymorphisme : une boucle, plusieurs classes
Python
class Task:
    def __init__(self, exp):
        self.exp = exp

    def reward(self):
        return self.exp

class BonusTask(Task):
    def reward(self):
        return self.exp * 2

class Tutorial(Task):
    def reward(self):
        return 0

tasks = [Task(10), BonusTask(10), Tutorial(10)]
print([task.reward() for task in tasks])
print(sum(task.reward() for task in tasks))
Résultatrésultat enregistré, vous pouvez le vérifier
[10, 20, 0]
30
L’ordre de recherche des méthodes (MRO)
Python
class Exercise:
    def describe(self):
        return "tâche"

class Timed(Exercise):
    def describe(self):
        return "tâche chronométrée"

class Scored(Exercise):
    def describe(self):
        return "tâche à points"

class Quiz(Timed, Scored):
    pass

print(Quiz().describe())
print([cls.__name__ for cls in Quiz.__mro__])
Résultatrésultat enregistré, vous pouvez le vérifier
tâche chronométrée
['Quiz', 'Timed', 'Scored', 'Exercise', 'object']
Une famille d’exceptions personnalisées
Python
class CodeWorldsError(Exception):
    pass

class NoFuelError(CodeWorldsError):
    pass

class LockedWorldError(CodeWorldsError):
    pass

for error in [NoFuelError("Plus de carburant"), LockedWorldError("Le monde 9 est verrouillé")]:
    try:
        raise error
    except CodeWorldsError as caught:
        print(type(caught).__name__, "->", caught)
Résultatrésultat enregistré, vous pouvez le vérifier
NoFuelError -> Plus de carburant
LockedWorldError -> Le monde 9 est verrouillé

Bonnes pratiques

#
  • N’héritez que lorsque l’objet de la classe dérivée « est » vraiment un objet de la classe de base. S’il se contente de l’utiliser, stockez-le comme attribut.
  • Évitez les hiérarchies profondes. Deux ou trois niveaux suffisent généralement, et chaque niveau supplémentaire complique la recherche de l’origine d’une méthode.
  • Faites dériver vos exceptions personnalisées d’une classe de base commune. Un seul except sur la classe de base traite alors toute la famille d’erreurs.

Entrées associées

#

Vous voyez une erreur ou il manque un exemple ? Écrivez-nous.