Programmation Orientee Objet en Python : Guide Complet avec Exemples Pratiques

Maitrisez la POO en Python : heritage, polymorphisme, encapsulation. Guide complet avec exemples de code, bonnes pratiques et pieges a eviter pour les developpeurs.

Mahmoud DEVO
Mahmoud DEVO
December 27, 2025 7 min read
Programmation Orientee Objet en Python : Guide Complet avec Exemples Pratiques

Introduction

La Programmation Orientee Objet (POO) est un paradigme de programmation qui structure le code autour d’objets plutot que de fonctions et de logique procedurale. En Python, la POO est au coeur du langage : tout est objet, des simples entiers aux fonctions en passant par les modules.

Lorsque vous developpez une application ou un service en Python, il est crucial de comprendre les concepts fondamentaux de la POO pour creer des classes et des objets efficaces. La POO offre plusieurs avantages majeurs :

  • Reutilisabilite : Le code peut etre reutilise grace a l’heritage
  • Modularite : Les objets peuvent etre developpes et testes independamment
  • Maintenabilite : Le code est plus facile a maintenir et a faire evoluer
  • Abstraction : Les details d’implementation sont caches derriere des interfaces claires

Dans cet article, nous allons explorer les principes de base de la POO en Python, couvrir les concepts cles tels que l’heritage, le polymorphisme et l’encapsulation, et fournir des exemples pratiques pour vous aider a bien comprendre ces notions.

Note : Ce guide suppose une connaissance de base de Python. Si vous debutez, je vous recommande de vous familiariser avec les types de donnees et les fonctions avant de plonger dans la POO.

Creation d’une classe

Pour commencer, nous allons creer une simple classe en Python. Une classe est un modele (ou “blueprint”) qui definit les attributs et les comportements que les objets de cette classe possederont.

Syntaxe de base

class Personne:
    """Classe representant une personne."""

    def __init__(self, nom, age):
        """Initialise une nouvelle personne.

        Args:
            nom: Le nom de la personne
            age: L'age de la personne
        """
        self.nom = nom
        self.age = age

    def presenter(self):
        """Affiche une presentation de la personne."""
        print(f"Bonjour, je m'appelle {self.nom} et j'ai {self.age} ans.")

    def anniversaire(self):
        """Incremente l'age de la personne d'un an."""
        self.age += 1
        print(f"Joyeux anniversaire {self.nom} ! Vous avez maintenant {self.age} ans.")

Comprendre les elements cles

  • __init__ : Le constructeur, appele automatiquement lors de la creation d’un objet
  • self : Reference a l’instance courante de la classe
  • Attributs d’instance : Variables propres a chaque objet (self.nom, self.age)
  • Methodes : Fonctions definies dans la classe qui operent sur les objets

Utilisation de la classe

# Creation d'instances
alice = Personne("Alice", 30)
bob = Personne("Bob", 25)

# Appel de methodes
alice.presenter()  # Bonjour, je m'appelle Alice et j'ai 30 ans.
bob.anniversaire() # Joyeux anniversaire Bob ! Vous avez maintenant 26 ans.

# Acces aux attributs
print(alice.nom)   # Alice
print(bob.age)     # 26

Heritage

L’heritage est l’une des fonctionnalites les plus importantes de la POO. Il permet aux classes de heriter des attributs et methodes d’autres classes, ce qui facilite le partage du code et reduit la duplication.

Heritage simple

class Employe(Personne):
    """Classe representant un employe, herite de Personne."""

    def __init__(self, nom, age, salaire, poste):
        # Appel du constructeur parent
        super().__init__(nom, age)
        self.salaire = salaire
        self.poste = poste

    def presenter(self):
        """Surcharge de la methode presenter."""
        super().presenter()
        print(f"Je suis {self.poste} et mon salaire est de {self.salaire} euros.")

    def augmenter_salaire(self, pourcentage):
        """Augmente le salaire d'un certain pourcentage."""
        self.salaire *= (1 + pourcentage / 100)
        print(f"Nouveau salaire : {self.salaire:.2f} euros")

Heritage multiple

Python supporte l’heritage multiple, permettant a une classe d’heriter de plusieurs classes parentes :

class Artiste:
    """Classe representant un artiste."""

    def __init__(self, talent):
        self.talent = talent

    def performer(self):
        print(f"Je performe avec mon talent : {self.talent}")


class EmployeArtiste(Employe, Artiste):
    """Un employe qui est aussi artiste."""

    def __init__(self, nom, age, salaire, poste, talent):
        Employe.__init__(self, nom, age, salaire, poste)
        Artiste.__init__(self, talent)

    def presenter(self):
        super().presenter()
        self.performer()


# Utilisation
musicien = EmployeArtiste("Marie", 28, 3500, "Developpeur", "Guitare")
musicien.presenter()

Attention : L’heritage multiple peut creer des problemes de complexite (probleme du diamant). Utilisez-le avec parcimonie.

Polymorphisme

Le polymorphisme est la capacite d’objets de types differents a repondre a la meme interface. En Python, le polymorphisme est naturel grace au “duck typing” : si un objet se comporte comme un canard, c’est un canard.

Polymorphisme par heritage

from abc import ABC, abstractmethod


class Animal(ABC):
    """Classe abstraite representant un animal."""

    def __init__(self, nom):
        self.nom = nom

    @abstractmethod
    def faire_un_son(self):
        """Methode abstraite que chaque animal doit implementer."""
        pass

    def se_presenter(self):
        print(f"Je suis {self.nom}")


class Chien(Animal):
    def faire_un_son(self):
        print(f"{self.nom} aboie : Wouf wouf !")


class Chat(Animal):
    def faire_un_son(self):
        print(f"{self.nom} miaule : Miaou !")


class Vache(Animal):
    def faire_un_son(self):
        print(f"{self.nom} meugle : Meuh !")

Utilisation polymorphe

def faire_parler_animaux(animaux):
    """Fonction qui fait parler tous les animaux."""
    for animal in animaux:
        animal.se_presenter()
        animal.faire_un_son()
        print()


# Creation d'une liste d'animaux
animaux = [
    Chien("Rex"),
    Chat("Whiskers"),
    Vache("Marguerite")
]

faire_parler_animaux(animaux)

Le polymorphisme permet de traiter des objets de types differents de maniere uniforme, rendant le code plus flexible et extensible.

Encapsulation

L’encapsulation est le principe de cacher les details d’implementation internes d’une classe et d’exposer uniquement une interface publique. En Python, on utilise des conventions de nommage pour indiquer le niveau d’acces.

Niveaux d’acces en Python

PrefixeAccesDescription
attributPublicAccessible partout
_attributProtegeConvention : usage interne
__attributPriveName mangling applique

Exemple complet

class CompteBancaire:
    """Classe representant un compte bancaire avec encapsulation."""

    def __init__(self, numero_compte, solde_initial=0):
        self.__numero_compte = numero_compte  # Prive
        self.__solde = solde_initial          # Prive
        self._historique = []                 # Protege

    @property
    def numero_compte(self):
        """Getter pour le numero de compte (lecture seule)."""
        return self.__numero_compte

    @property
    def solde(self):
        """Getter pour le solde."""
        return self.__solde

    def deposer(self, montant):
        """Depose un montant sur le compte."""
        if montant <= 0:
            raise ValueError("Le montant doit etre positif")
        self.__solde += montant
        self._historique.append(f"Depot : +{montant} euros")
        return self.__solde

    def retirer(self, montant):
        """Retire un montant du compte."""
        if montant <= 0:
            raise ValueError("Le montant doit etre positif")
        if montant > self.__solde:
            raise ValueError("Solde insuffisant")
        self.__solde -= montant
        self._historique.append(f"Retrait : -{montant} euros")
        return self.__solde

    def afficher_historique(self):
        """Affiche l'historique des transactions."""
        for transaction in self._historique:
            print(transaction)

Utilisation avec les properties

compte = CompteBancaire("FR7612345678901234567890123", 1000)

# Acces en lecture via property
print(f"Numero : {compte.numero_compte}")
print(f"Solde : {compte.solde} euros")

# Operations
compte.deposer(500)
compte.retirer(200)

print(f"Nouveau solde : {compte.solde} euros")
compte.afficher_historique()

# Tentative d'acces direct (echoue)
# compte.__solde = 999999  # AttributeError

Bonnes Pratiques

Pour ecrire du code POO de qualite en Python, suivez ces recommandations :

1. Privilegiez la composition a l’heritage

# Moins bon : heritage excessif
class Voiture(Moteur, Roues, Carrosserie):
    pass

# Meilleur : composition
class Voiture:
    def __init__(self):
        self.moteur = Moteur()
        self.roues = [Roue() for _ in range(4)]
        self.carrosserie = Carrosserie()

2. Respectez le principe de responsabilite unique

Chaque classe doit avoir une seule raison de changer.

# Moins bon : classe qui fait trop de choses
class Utilisateur:
    def __init__(self, nom, email):
        self.nom = nom
        self.email = email

    def sauvegarder_en_base(self):  # Responsabilite BDD
        pass

    def envoyer_email(self):  # Responsabilite Email
        pass

# Meilleur : separation des responsabilites
class Utilisateur:
    def __init__(self, nom, email):
        self.nom = nom
        self.email = email

class UtilisateurRepository:
    def sauvegarder(self, utilisateur):
        pass

class EmailService:
    def envoyer(self, destinataire, message):
        pass

3. Utilisez les dataclasses pour les classes de donnees

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float

    def distance_origine(self):
        return (self.x ** 2 + self.y ** 2) ** 0.5

p = Point(3, 4)
print(p)  # Point(x=3, y=4)
print(p.distance_origine())  # 5.0

4. Documentez vos classes avec des docstrings

Utilisez toujours des docstrings pour expliquer le but de vos classes et methodes.

Pieges Courants

Evitez ces erreurs frequentes en POO Python :

1. Oublier self dans les methodes

# Erreur courante
class MaClasse:
    def ma_methode():  # Manque self !
        print("Hello")

# Correct
class MaClasse:
    def ma_methode(self):
        print("Hello")

2. Attributs de classe mutables partages

# Piege : liste partagee entre toutes les instances !
class MauvaiseClasse:
    items = []  # Attribut de classe

    def ajouter(self, item):
        self.items.append(item)

a = MauvaiseClasse()
b = MauvaiseClasse()
a.ajouter("x")
print(b.items)  # ["x"] - Surprise !

# Solution : initialiser dans __init__
class BonneClasse:
    def __init__(self):
        self.items = []  # Attribut d'instance

    def ajouter(self, item):
        self.items.append(item)

3. Ne pas appeler super().init()

# Piege : oublier d'appeler le constructeur parent
class Enfant(Parent):
    def __init__(self, valeur):
        # Oubli de super().__init__()
        self.valeur = valeur  # Parent non initialise !

# Correct
class Enfant(Parent):
    def __init__(self, valeur):
        super().__init__()  # Toujours appeler le parent
        self.valeur = valeur

4. Confondre == et is

class Personne:
    def __init__(self, nom):
        self.nom = nom

p1 = Personne("Alice")
p2 = Personne("Alice")

print(p1 == p2)  # False (sans __eq__)
print(p1 is p2)  # False (objets differents)

# Solution : implementer __eq__
class Personne:
    def __init__(self, nom):
        self.nom = nom

    def __eq__(self, other):
        if not isinstance(other, Personne):
            return False
        return self.nom == other.nom

Conclusion

La Programmation Orientee Objet est un pilier essentiel du developpement Python moderne. Dans cet article, nous avons explore :

  • Les classes et objets : La base de la POO avec __init__ et self
  • L’heritage : Simple et multiple pour reutiliser le code
  • Le polymorphisme : Traiter differents types de maniere uniforme
  • L’encapsulation : Proteger les donnees avec les conventions Python

En appliquant les bonnes pratiques et en evitant les pieges courants, vous serez en mesure de creer des applications Python robustes, maintenables et evolutives.

La prochaine etape ? Explorez les design patterns (Singleton, Factory, Observer) pour aller encore plus loin dans la maitrise de la POO.

Exercices Pratiques

Pour consolider vos connaissances, essayez ces exercices :

  1. Systeme de gestion de bibliotheque : Creez des classes Livre, Membre et Bibliotheque avec des methodes pour emprunter et retourner des livres.

  2. Jeu de cartes : Implementez les classes Carte, Paquet et Joueur pour un jeu de cartes simple.

  3. Systeme de facturation : Creez une hierarchie de classes Produit, ProduitPhysique, ProduitNumerique avec calcul de taxes et livraison.

  4. Gestionnaire de taches : Implementez un systeme de taches avec Tache, TacheUrgente, TacheRecurrente en utilisant l’heritage et le polymorphisme.

Advertisement

In-Article Ad

Dev Mode

Share this article

Mahmoud DEVO

Mahmoud DEVO

Senior Full-Stack Developer

I'm a passionate full-stack developer with 10+ years of experience building scalable web applications. I write about Vue.js, Node.js, PostgreSQL, and modern DevOps practices.

Enjoyed this article?

Subscribe to get more tech content delivered to your inbox.

Related Articles