🐍python

Programmation orientee objet en Python : classes et heritage

30 mars 2026 5 min de lecture

Introduction : Pourquoi la POO ?

Salut ! Si tu es en spécialité NSI, tu as sûrement déjà écrit des fonctions et manipulé des listes ou des dictionnaires. C'est ce qu'on appelle la programmation procédurale. Mais pour des projets plus complexes, comme un jeu vidéo ou une application de gestion, une autre approche est bien plus puissante : la Programmation Orientée Objet (POO).

Imagine que tu développes un jeu. Tu as des personnages, des ennemis, des objets... Avec la POO, tu vas créer un modèle (une classe) pour chaque type d'élément. Chaque personnage du jeu sera alors une instance de la classe Personnage, avec ses propres caractéristiques (points de vie, position) et ses propres actions (attaquer, se déplacer). C'est une façon de penser ton code qui le rend plus organisé, plus facile à maintenir et à faire évoluer. C'est un pilier du programme de NSI et une compétence essentielle pour tout développeur.

Les bases : Créer sa première classe

Une classe est un plan de construction, un moule. Pour définir une classe en Python, on utilise le mot-clé class.

La méthode __init__ et les attributs

La méthode spéciale __init__ est le constructeur. C'est elle qui est appelée automatiquement quand tu crées un nouvel objet (une instance) de la classe. C'est ici que tu vas initialiser les attributs, les variables qui caractérisent l'objet.

Prenons un exemple concret : une classe EtudiantNSI.

class EtudiantNSI:
def __init__(self, nom, prenom, moyenne):
self.nom = nom
self.prenom = prenom
self.moyenne = moyenne
self.notes = [] # Un attribut avec une valeur par défaut

def ajouter_note(self, nouvelle_note):
"""Une méthode pour modifier l'état de l'objet."""
self.notes.append(nouvelle_note)
self.moyenne = sum(self.notes) / len(self.notes)

def est_admis(self):
"""Une méthode qui renvoie une information."""
return self.moyenne >= 10

# Création d'instances
alice = EtudiantNSI("Martin", "Alice", 15)
bob = EtudiantNSI("Durand", "Bob", 8)

# Utilisation des méthodes
alice.ajouter_note(17)
print(f"{alice.prenom} est admis ? {alice.est_admis()}") # Affiche : Alice est admis ? True
print(f"{bob.prenom} est admis ? {bob.est_admis()}") # Affiche : Bob est admis ? False

Points clés à retenir :

  • self : représente l'instance courante. Il doit être le premier paramètre de chaque méthode d'instance.
  • Attributs (comme self.nom) : ce sont les données de l'objet.
  • Méthodes (comme ajouter_note) : ce sont les fonctions qui définissent le comportement de l'objet.

L'héritage : Éviter la répétition et spécialiser

L'héritage est un concept fondamental de la POO. Il permet de créer une nouvelle classe (classe fille) à partir d'une classe existante (classe mère ou parente). La classe fille hérite de tous les attributs et méthodes de la classe mère, et peut en ajouter de nouveaux ou en redéfinir.

Pourquoi c'est génial ? Pour la réutilisation du code et la spécialisation.

Exemple : Dans ton jeu, tu as une classe Personnage générique. Les Guerrier et les Mage sont des types de personnages particuliers.

class Personnage:
def __init__(self, nom, points_de_vie):
self.nom = nom
self.pv = points_de_vie

def attaquer(self, cible):
print(f"{self.nom} attaque {cible.nom} !")

class Guerrier(Personnage): # Guerrier hérite de Personnage
def __init__(self, nom, points_de_vie, force):
# On appelle le constructeur de la classe parente
super().__init__(nom, points_de_vie)
# On ajoute un attribut spécifique au Guerrier
self.force = force

# On redéfinit (surcharge) la méthode attaquer
def attaquer(self, cible):
degats = self.force * 2
cible.pv -= degats
print(f"{self.nom} frappe violemment {cible.nom} et lui inflige {degats} dégâts !" )

class Mage(Personnage):
def __init__(self, nom, points_de_vie, mana):
super().__init__(nom, points_de_vie)
self.mana = mana

def lancer_sort(self, cible):
if self.mana >= 10:
self.mana -= 10
cible.pv -= 15
print(f"{self.nom} lance un sort sur {cible.nom} !")

# Utilisation
conan = Guerrier("Conan", 100, 25)
merlin = Mage("Merlin", 80, 50)

conan.attaquer(merlin) # Utilise la méthode de Guerrier
print(f"PV de Merlin : {merlin.pv}")
merlin.lancer_sort(conan) # Méthode spécifique au Mage
print(f"PV de Conan : {conan.pv}")

L'héritage crée une hiérarchie logique et évite de dupliquer le code commun (comme nom et pv).

Concepts avancés : Polymorphisme et encapsulation

Le polymorphisme

Ce terme un peu barbare signifie "qui peut prendre plusieurs formes". En pratique, grâce à l'héritage, tu peux traiter un objet d'une classe fille comme un objet de la classe mère. Par exemple, tu peux avoir une liste de Personnage contenant des Guerrier et des Mage, et les faire tous attaquer via une boucle. Chaque objet utilisera sa propre version de la méthode attaquer : c'est le polymorphisme.

L'encapsulation

C'est le principe qui consiste à protéger les données internes d'un objet. En Python, c'est plus une convention qu'une règle stricte. On utilise :

  • Un seul underscore _attribut : pour signaler qu'un attribut est "protégé" (à usage interne). Il reste accessible, mais c'est une indication pour le programmeur.
  • Deux underscores __attribut : pour "mangler" le nom de l'attribut et le rendre plus difficile à accéder accidentellement depuis l'extérieur de la classe. C'est une forme de protection faible.

L'idée est de fournir des méthodes publiques (interface) pour interagir avec l'objet, plutôt que de manipuler ses attributs directement. Cela garantit un meilleur contrôle.

Projet NSI : Modéliser une bibliothèque

Mettons tout ça en pratique avec un mini-projet typique de NSI : un système de gestion de bibliothèque.

class Livre:
def __init__(self, titre, auteur, isbn):
self.titre = titre
self.auteur = auteur
self.isbn = isbn
self.disponible = True

def emprunter(self):
if self.disponible:
self.disponible = False
return True
return False

def rendre(self):
self.disponible = True

class Utilisateur:
def __init__(self, nom, id_user):
self.nom = nom
self.id = id_user
self.livres_empruntes = []

def emprunter_livre(self, livre):
if livre.emprunter():
self.livres_empruntes.append(livre)
print(f"{self.nom} a emprunté '{livre.titre}'.")
else:
print(f"Le livre '{livre.titre}' n'est pas disponible.")

# Création des objets
livre1 = Livre("Le Petit Prince", "Saint-Exupéry", "12345")
livre2 = Livre("1984", "George Orwell", "67890")
alice = Utilisateur("Alice", "U001")

# Simulation
alice.emprunter_livre(livre1)
alice.emprunter_livre(livre2)
alice.emprunter_livre(livre1) # Tentative de ré-emprunt

livre1.rendre()
print(f"{livre1.titre} est disponible : {livre1.disponible}")

Ce modèle simple peut être étendu avec une classe Bibliotheque qui gérerait des listes de livres et d'utilisateurs, ou avec un héritage pour différencier les types de livres (Roman, BD, Manuel).

La POO, c'est avant tout une nouvelle façon de penser ton code. Commence par identifier les entités (les objets) de ton problème, puis modélise-les avec des classes. Avec un peu de pratique, cela deviendra naturel et te permettra de réaliser des projets NSI bien plus ambitieux et structurés !

📚 Pour aller plus loin

Questions fréquentes

Quelle est la différence entre une classe et un objet (instance) ?

La classe est le plan, le modèle. Par exemple, le plan d'une voiture. L'objet (ou instance) est la réalisation concrète de ce plan. Par exemple, ta voiture personnelle, avec sa couleur, son immatriculation. Tu peux créer autant d'objets que tu veux à partir d'une même classe, chacun avec ses propres valeurs d'attributs.

À quoi sert vraiment le mot-clé 'self' dans une méthode ?

'self' est une référence à l'instance courante de la classe. Quand tu appelles une méthode comme `alice.ajouter_note(17)`, Python passe automatiquement l'objet `alice` en premier argument à la méthode. À l'intérieur de la méthode, `self` représente donc `alice`. Cela permet à chaque objet d'accéder et de modifier ses propres données.

Quand dois-je utiliser l'héritage en POO ?

Utilise l'héritage quand tu as plusieurs entités qui partagent des caractéristiques et des comportements communs, mais qui ont aussi des spécificités. Par exemple, 'Véhicule' (classe mère) avec 'Voiture' et 'Moto' (classes filles). Si la relation "est un" est vraie ("une Voiture EST UN Véhicule"), l'héritage est généralement approprié. Sinon, la composition (avoir un objet dans un autre) est souvent meilleure.

La POO est-elle obligatoire pour réussir en NSI ?

Elle fait partie intégrante du programme de Terminale NSI. Tu dois savoir lire, comprendre, et écrire des classes simples avec héritage. Pour les projets, même modestes, utiliser la POO montre une bonne maîtrise des concepts et est très apprécié. C'est aussi une compétence fondamentale pour la poursuite d'études en informatique.

Bravo ! Tu as lu cet article
Inscris-toi pour sauvegarder ta progression et gagner des XP
Creer mon compte
POO Pythonclasses Python NSI
Pixel