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.
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.
- Introduction et Installation
- Rappel Python
- Fonctions avancees et lambdas
- Classes et objets
- Heritage et polymorphisme
Encapsulation, properties et setters
Objectifs pédagogiques
_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.
Conventions Python
Python ne force pas la confidentialité (contrairement à Java). Il utilise des conventions basées sur le nom.
| Convention | Signification | Effet réel |
|---|---|---|
nom | Public | Accès libre, fait partie de l’API |
_nom | Protégé (convention) | "Ne touche pas, sauf si tu sais ce que tu fais" |
__nom | Privé (name mangling) | Renommé en _NomClasse__nom |
nom_ | Évite collision avec mot-clé | Ex : class_ au lieu de class |
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é__ 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
class Temperature:
def __init__(self, celsius):
self.celsius = celsius
t = Temperature(25)
t.celsius = -500 # absurde !
print(t.celsius) # -500Aucune 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.
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 !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.
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 setterProperty complète avec getter, setter, deleter
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 nomCas pratique : CompteBancaire avec validation
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 # ValueErrorHéritage simple
Objectifs pédagogiques
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.
Chien est-un Animal.Premier exemple
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.
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’animala.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.
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__init__, vous devez appeler super().__init__(...) pour initialiser les attributs de la mère. Oubli = bugs garantis.Vérifier la parenté : isinstance et issubclass
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)) # Falseisinstance(x, Animal) plutôt que type(x) == Animal. La première forme respecte l’héritage.Quand utiliser l’héritage ?
| Relation | Héritage ? |
|---|---|
| Chien est-un Animal | Oui |
| Roman est-un Livre | Oui |
| Voiture a-un Moteur | Non — composition |
| Bibliothèque contient des Livres | Non — composition |
Cas concret : application bibliothèque
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.epubHiérarchies courantes en Python
Lambda, map, filter, reduce
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
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
lambda parametres: expression
Comparaison
def doubler(x):
return x * 2
doubler_lambda = lambda x: x * 2
print(doubler(5)) # 10
print(doubler_lambda(5)) # 10def 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
somme = lambda a, b: a + b print(somme(3, 4)) # 7 est_pair = lambda n: n % 2 == 0 print(est_pair(8)) # True
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().
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
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
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']
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 CodeFAQ
Combien de temps pour apprendre Python Intermédiaire POO ?
Faut-il des prérequis ?
Par où commencer concrètement ?
📬 Tu veux recevoir ce type de guide chaque semaine ? Abonne-toi gratuitement — code réel, zéro blabla.