Python Intermédiaire POO en pratique : le code et les commandes qui comptent vraiment

Python Intermédiaire POO : l'essentiel en un article — vrai code, schémas et étapes concrètes, extraits d'un cours de 36 leçons.

Python Intermédiaire POO en pratique : le code et les commandes qui comptent vraiment

Pas de théorie interminable ici : on ouvre le terminal et on pratique. Voici l'essentiel de Python Intermédiaire POO, extrait directement d'un cours complet de 36 leçons — avec du vrai code que tu peux copier-coller maintenant.

tl;dr
  • Introduction et Installation
  • Rappel Python
  • Fonctions avancees et lambdas
  • Classes et objets
  • Heritage et polymorphisme
~$ cat ./parcours.md # Python Intermédiaire POO — 10 chapitres
01
Introduction et Installation
→ Présentation du cours→ Installer Python, VS Code et un environnement virtuel+ 1 autres leçons
02
Rappel Python
→ Variables, types et structures de données essentielles→ Conditions, boucles et compréhensions de liste+ 1 autres leçons
03
Fonctions avancées et lambdas
→ Lambda, map, filter, reduce→ *args, **kwargs et arguments par défaut+ 1 autres leçons
04
Classes et objets
→ Pourquoi la POO ? Classes vs instances→ Définir une classe : __init__, attributs et méthodes+ 2 autres leçons
05
Héritage et polymorphisme
→ Héritage simple→ Héritage multiple et MRO+ 1 autres leçons
06
Méthodes spéciales dunder
→ __str__, __repr__, __len__→ Opérateurs surchargés : __add__, __eq__, __lt__+ 1 autres leçons
07
Modules et paquets
→ Import, modules et namespaces→ Créer son propre paquet avec __init__.py+ 1 autres leçons
08
Gestion d'erreurs et exceptions
→ try, except, else, finally→ Exceptions personnalisées+ 1 autres leçons
🏁
Projet final (+ 2 chapitres en chemin)
→ Tu repars avec un projet concret et démontrable

Encapsulation, properties et setters

NOTEObjectif — Apprendre à protéger les attributs internes d’un objet et à valider leur modification grâce aux properties, sans alourdir l’interface publique.

Objectifs pédagogiques

TIPÀ l’issue de ce module — Vous saurez utiliser les conventions _x et __x, transformer un attribut en property pour ajouter de la validation, et savoir quand le faire.

Qu’est-ce que l’encapsulation ?

L’encapsulation consiste à cacher les détails internes d’une classe et n’exposer qu’une interface contrôlée.

NOTEAnalogie — Une télécommande de TV : vous appuyez sur "volume +" sans savoir ce qui se passe dans les circuits. L’interface est simple, l’interne est protégé.

Conventions Python

Python ne force pas la confidentialité (contrairement à Java). Il utilise des conventions basées sur le nom.

ConventionSignificationEffet réel
nomPublicAccès libre, fait partie de l’API
_nomProtégé (convention)"Ne touche pas, sauf si tu sais ce que tu fais"
__nomPrivé (name mangling)Renommé en _NomClasse__nom
nom_Évite collision avec mot-cléEx : class_ au lieu de class
output
class CompteBancaire:
    def __init__(self, titulaire, solde):
        self.titulaire = titulaire        # public
        self._solde = solde               # convention : ne pas toucher
        self.__pin = "1234"                # privé (name mangling)

c = CompteBancaire("Alice", 1000)
print(c.titulaire)                  # OK
print(c._solde)                     # accessible mais déconseillé
# print(c.__pin)                    # AttributeError !
print(c._CompteBancaire__pin)       # accessible avec le nom manglé
WARNINGLe __ n’est pas une sécurité — C’est un mécanisme pour éviter les collisions accidentelles dans l’héritage. Pour de la vraie sécurité, utilisez des permissions au niveau système.

Le problème sans encapsulation

output
class Temperature:
    def __init__(self, celsius):
        self.celsius = celsius

t = Temperature(25)
t.celsius = -500          # absurde !
print(t.celsius)          # -500

Aucune validation. Le -500 est impossible (zéro absolu = -273.15) mais Python l’accepte.

@property : transformer un attribut en méthode

Un @property fait qu’un appel comme obj.attribut exécute en réalité une méthode, sans changer la syntaxe d’utilisation.

output
class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius

    @property
    def celsius(self):
        return self._celsius

    @celsius.setter
    def celsius(self, valeur):
        if valeur < -273.15:
            raise ValueError("Sous le zéro absolu, impossible")
        self._celsius = valeur

t = Temperature(25)
print(t.celsius)            # 25 (appelle le getter)
t.celsius = 30              # appelle le setter, OK
t.celsius = -300            # ValueError !
TIPLe superpouvoir — Vous gardez la syntaxe t.celsius (simple) mais ajoutez du contrôle invisible. Le code utilisateur n’a rien à changer.

Property en lecture seule

Pour un attribut calculé (dérivé d’autres) qu’on ne doit pas pouvoir modifier directement.

output
class Cercle:
    def __init__(self, rayon):
        self.rayon = rayon

    @property
    def diametre(self):
        return self.rayon * 2

    @property
    def aire(self):
        from math import pi
        return pi * self.rayon ** 2

c = Cercle(5)
print(c.diametre)         # 10
print(c.aire)             # 78.539...
# c.aire = 100            # AttributeError : pas de setter

Property complète avec getter, setter, deleter

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

    @property
    def nom(self):
        return self._nom

    @nom.setter
    def nom(self, valeur):
        if not isinstance(valeur, str) or len(valeur) < 2:
            raise ValueError("Nom invalide")
        self._nom = valeur.title()      # normalisation

    @nom.deleter
    def nom(self):
        print("Suppression du nom")
        self._nom = None

p = Personne("alice")
print(p.nom)              # Alice (normalisé)
p.nom = "bob"
print(p.nom)              # Bob
del p.nom                 # Suppression du nom

Cas pratique : CompteBancaire avec validation

output
class CompteBancaire:
    def __init__(self, titulaire, solde=0):
        self.titulaire = titulaire
        self._solde = 0
        self.solde = solde         # passe par le setter !

    @property
    def solde(self):
        return self._solde

    @solde.setter
    def solde(self, valeur):
        if valeur < 0:
            raise ValueError("Solde négatif interdit")
        self._solde = valeur

    def deposer(self, montant):
        if montant <= 0:
            raise ValueError("Montant doit être positif")
        self.solde += montant       # passe par le setter

    def retirer(self, montant):
        if montant > self._solde:
            raise ValueError("Solde insuffisant")
        self.solde -= montant

c = CompteBancaire("Alice", 1000)
c.deposer(500)
print(c.solde)            # 1500
# c.solde = -100          # ValueError

Héritage simple

NOTEObjectif — Apprendre à créer une nouvelle classe en partant d’une existante, en réutilisant son code et en l’adaptant. C’est le mécanisme clé pour éviter la duplication de code en POO.

Objectifs pédagogiques

TIPÀ l’issue de ce module — Vous saurez définir une classe fille qui hérite d’une classe mère, surcharger ses méthodes et appeler la version parente avec super().

Le concept

L’héritage permet de créer une classe spécialisée à partir d’une classe générale. La classe fille récupère tout ce que la classe mère propose, puis ajoute ou modifie.

NOTEAnalogie — Un Chien est un Animal. Tout chien hait des comportements d’animal (manger, dormir), plus des comportements spécifiques (aboyer). On dit que Chien est-un Animal.

Premier exemple

output
class Animal:
    def __init__(self, nom, age):
        self.nom = nom
        self.age = age

    def manger(self):
        print(f"{self.nom} mange")

    def dormir(self):
        print(f"{self.nom} dort")


class Chien(Animal):
    def aboyer(self):
        print(f"{self.nom} : Wouaf !")


rex = Chien("Rex", 5)
rex.manger()              # hérité d’Animal
rex.dormir()              # hérité d’Animal
rex.aboyer()              # propre à Chien
print(rex.age)            # hérité

Chien ne définit pas __init__ : Python utilise automatiquement celui d’Animal.

Surcharger (override) une méthode

La classe fille peut redéfinir une méthode de la mère pour adapter son comportement.

output
class Animal:
    def parler(self):
        print("Bruit générique d’animal")


class Chien(Animal):
    def parler(self):
        print("Wouaf !")


class Chat(Animal):
    def parler(self):
        print("Miaou")


for a in [Chien(), Chat(), Animal()]:
    a.parler()
# Wouaf !
# Miaou
# Bruit générique d’animal
TIPPolymorphisme — Le même appel a.parler() produit un résultat différent selon la classe réelle de a. C’est l’un des 4 piliers de la POO.

super() : appeler la méthode parente

Quand on surcharge une méthode, on veut souvent compléter le comportement parent plutôt que le remplacer.

output
class Animal:
    def __init__(self, nom, age):
        self.nom = nom
        self.age = age

    def description(self):
        return f"{self.nom}, {self.age} ans"


class Chien(Animal):
    def __init__(self, nom, age, race):
        super().__init__(nom, age)        # appelle Animal.__init__
        self.race = race

    def description(self):
        base = super().description()       # appelle Animal.description
        return f"{base}, race {self.race}"


rex = Chien("Rex", 5, "Labrador")
print(rex.description())     # Rex, 5 ans, race Labrador
WARNINGRègle — Dès qu’une classe fille a son propre __init__, vous devez appeler super().__init__(...) pour initialiser les attributs de la mère. Oubli = bugs garantis.

Vérifier la parenté : isinstance et issubclass

output
rex = Chien("Rex", 5, "Labrador")

print(isinstance(rex, Chien))      # True
print(isinstance(rex, Animal))     # True (héritage)
print(isinstance(rex, Chat))       # False

print(issubclass(Chien, Animal))   # True
print(issubclass(Animal, Chien))   # False
TIPPythonic — Utilisez isinstance(x, Animal) plutôt que type(x) == Animal. La première forme respecte l’héritage.

Quand utiliser l’héritage ?

RelationHéritage ?
Chien est-un AnimalOui
Roman est-un LivreOui
Voiture a-un MoteurNon — composition
Bibliothèque contient des LivresNon — composition
NOTERègle d’or — Préférez la composition à l’héritage. Si la relation n’est pas une vraie spécialisation, utilisez un attribut plutôt qu’un héritage.

Cas concret : application bibliothèque

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

    def description(self):
        return f"{self.titre} de {self.auteur}"


class Roman(Livre):
    def __init__(self, titre, auteur, isbn, genre):
        super().__init__(titre, auteur, isbn)
        self.genre = genre

    def description(self):
        return f"{super().description()} -- roman {self.genre}"


class LivreNumerique(Livre):
    def __init__(self, titre, auteur, isbn, format_fichier):
        super().__init__(titre, auteur, isbn)
        self.format_fichier = format_fichier

    def telecharger(self):
        print(f"Téléchargement de {self.titre}.{self.format_fichier}")


dune = Roman("Dune", "Herbert", "978...", "science-fiction")
ebook = LivreNumerique("1984", "Orwell", "978...", "epub")

print(dune.description())       # Dune de Herbert -- roman science-fiction
print(ebook.description())       # 1984 de Orwell
ebook.telecharger()              # Téléchargement de 1984.epub

Hiérarchies courantes en Python

Lambda, map, filter, reduce

NOTEObjectif — Découvrir les fonctions anonymes (lambda) et les fonctions d’ordre supérieur (map, filter, reduce), qui permettent de transformer et filtrer des données de manière très concise.

Objectifs pédagogiques

TIPÀ l’issue de ce module — Vous saurez quand utiliser une lambda, et choisir entre map/filter et une compréhension de liste selon le contexte.

Qu’est-ce qu’une lambda ?

Une lambda est une fonction anonyme (sans nom) tenant sur une seule ligne. On l’utilise pour des opérations courtes passées en argument à une autre fonction.

Syntaxe

output
lambda parametres: expression

Comparaison

output
def doubler(x):
    return x * 2

doubler_lambda = lambda x: x * 2

print(doubler(5))         # 10
print(doubler_lambda(5))  # 10
NOTEAnalogie — Une def classique, c’est comme créer une recette nommée dans un livre. Une lambda, c’est griffonner une recette sur un post-it que vous donnez tout de suite à quelqu’un.

Lambdas multi-paramètres

output
somme = lambda a, b: a + b
print(somme(3, 4))                       # 7

est_pair = lambda n: n % 2 == 0
print(est_pair(8))                       # True
WARNINGLimite — Une lambda ne contient qu’une seule expression. Pas de return explicite, pas de plusieurs lignes. Dès que c’est plus complexe, utilisez def.

map() : transformer chaque élément

map(fonction, iterable) applique la fonction à chaque élément et retourne un itérateur. On l’enveloppe souvent dans list().

output
prix = [10, 25, 7, 50]
prix_ttc = list(map(lambda p: p * 1.20, prix))
print(prix_ttc)        # [12.0, 30.0, 8.4, 60.0]

mots = ["python", "poo", "code"]
majuscules = list(map(str.upper, mots))
print(majuscules)      # ['PYTHON', 'POO', 'CODE']

Avec plusieurs séquences

output
a = [1, 2, 3]
b = [10, 20, 30]
sommes = list(map(lambda x, y: x + y, a, b))
print(sommes)          # [11, 22, 33]

filter() : garder ce qui passe le test

output
notes = [12, 8, 15, 6, 18, 11]
reussies = list(filter(lambda n: n >= 10, notes))
print(reussies)        # [12, 15, 18, 11]

mots = ["chat", "chien", "ours", "lion"]
courts = list(filter(lambda m: len(m) <= 4, mots))
print(courts)          # ['chat', 'ours', 'lion']
va-plus-loin

Cet article couvre les extraits les plus utiles — le cours complet Python Intermédiaire POO (11 chapitres, 36 leçons, exercices corrigés et projet final) t'emmène jusqu'au bout.

./acceder-au-cours-complet cours gratuit : Maîtriser Claude Code

FAQ

Combien de temps pour apprendre Python Intermédiaire POO ?
Avec une progression structurée (11 chapitres, 36 leçons courtes et pratiques), on atteint un niveau opérationnel en quelques semaines à raison de 30 à 60 minutes par jour. L'important est de pratiquer chaque notion immédiatement.
Faut-il des prérequis ?
Des bases en informatique suffisent. Si tu sais utiliser un terminal et lire du code simple, tu es prêt.
Par où commencer concrètement ?
Reproduis les commandes de cet article, puis suis le cours complet Python Intermédiaire POO : il enchaîne les 36 leçons dans l'ordre, avec exercices et projet final.

📬 Tu veux recevoir ce type de guide chaque semaine ? Abonne-toi gratuitement — code réel, zéro blabla.