0% ont trouvé ce document utile (0 vote)
8 vues18 pages

Poo Python Cours

Ce cours complet sur la programmation orientée objet en Python aborde les concepts fondamentaux tels que les classes, objets, méthodes, encapsulation, héritage, polymorphisme et abstraction. Il fournit des explications simples et des exemples détaillés pour aider les débutants à comprendre comment organiser et structurer leur code de manière efficace. Les avantages de la POO, tels que la réutilisabilité et la maintenance, sont également mis en avant.

Transféré par

rmzane.hajar
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOCX, PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
8 vues18 pages

Poo Python Cours

Ce cours complet sur la programmation orientée objet en Python aborde les concepts fondamentaux tels que les classes, objets, méthodes, encapsulation, héritage, polymorphisme et abstraction. Il fournit des explications simples et des exemples détaillés pour aider les débutants à comprendre comment organiser et structurer leur code de manière efficace. Les avantages de la POO, tels que la réutilisabilité et la maintenance, sont également mis en avant.

Transféré par

rmzane.hajar
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOCX, PDF, TXT ou lisez en ligne sur Scribd

🐍

Cours Complet
Programmation Orientée
Objet
en Python
Pour débutantes • Explications simples • Exemples détaillés

Ce cours couvre :
✅ Procédural vs POO
✅ Classes, Objets, Attributs, Méthodes
✅ Encapsulation (public, protégé, privé, getters/setters, @property)
✅ Héritage simple, multiple, super()
✅ Polymorphisme (overriding vs overloading)
✅ Abstraction (module abc)
✅ __str__, __repr__, __dict__, __doc__
✅ Garbage Collector et comptage de références
1. Programmation Procédurale vs POO
Avant de plonger dans la POO, comprenons d'abord la différence avec ce que tu connais
probablement déjà : la programmation procédurale.

🔧 La programmation procédurale
Imagine que tu dois gérer une bibliothèque. En procédural, tu crées des variables séparées
et des fonctions indépendantes qui agissent sur ces données.

# === STYLE PROCÉDURAL ===

# On définit les données séparément


nom_livre = "Le Petit Prince"
auteur_livre = "Antoine de Saint-Exupéry"
pages_livre = 96

# Les fonctions sont séparées des données


def afficher_livre(nom, auteur, pages):
print(f"📖 {nom} par {auteur} - {pages} pages")

afficher_livre(nom_livre, auteur_livre, pages_livre)

# Problème : si on a 100 livres, on crée 300 variables !

La Programmation Orientée Objet (POO)


En POO, on regroupe les données ET les fonctions qui les concernent dans une seule
structure appelée CLASSE. C'est comme une boîte bien organisée !

💡 Analogie La POO c'est comme une fiche d'identité : toutes les informations sur une
personne (nom, âge, adresse) sont regroupées ensemble, avec les actions que cette
personne peut faire (marcher, parler, manger).

# === STYLE POO ===

class Livre:
def __init__(self, nom, auteur, pages):
[Link] = nom # le nom du livre
[Link] = auteur # son auteur
[Link] = pages # nombre de pages

def afficher(self):
print(f"📖 {[Link]} par {[Link]} - {[Link]} pages")

# Créer un livre, c'est simple !


mon_livre = Livre("Le Petit Prince", "Saint-Exupéry", 96)
mon_livre.afficher()
# Résultat : 📖 Le Petit Prince par Saint-Exupéry - 96 pages
Les 4 grands avantages de la POO :
• 📦 Organisation : données + actions regroupées logiquement
• ♻️Réutilisabilité : une classe peut créer des centaines d'objets
• 🔧 Maintenance : modifier une classe modifie tous ses objets
• 📖 Lisibilité : le code représente le monde réel
2. Classe, Objet, Attribut, Méthode
📐 La Classe — le moule
💡 Analogie Une classe c'est comme le moule d'un gâteau. Le moule lui-même n'est pas
un gâteau, mais il permet d'en créer autant qu'on veut, tous de la même forme !

La classe définit la STRUCTURE : quelles informations elle contient et quelles actions elle
peut faire.

class Chien: # Le mot 'class' crée une classe, nom en majuscule


"""Classe qui représente un chien.""" # doc de la classe

def __init__(self, nom, race, age): # constructeur


"""Constructeur : appelé à chaque création."""
[Link] = nom # attribut 'nom'
[Link] = race # attribut 'race'
[Link] = age # attribut 'age'

📦 L'Objet — le gâteau fait avec le moule


Un objet est une INSTANCE de classe. C'est une réalisation concrète de la classe. Tu peux
créer autant d'objets que tu veux depuis la même classe.

# On crée des OBJETS (instances) à partir de la classe


rex = Chien("Rex", "Berger", 3) # objet 1
milou = Chien("Milou", "Fox", 2) # objet 2
lassie = Chien("Lassie", "Colley", 5) # objet 3

# Chaque objet est INDÉPENDANT


print([Link]) # Rex
print([Link]) # Fox

Les Attributs — les caractéristiques


Les attributs sont les DONNÉES stockées dans l'objet. C'est comme les caractéristiques sur
une fiche d'identité.

class Chien:
# ATTRIBUT DE CLASSE (partagé par tous les chiens)
espece = "Canis lupus familiaris"

def __init__(self, nom, age):


# ATTRIBUTS D'INSTANCE (uniques à chaque chien)
[Link] = nom # propre à cet objet
[Link] = age # propre à cet objet

rex = Chien("Rex", 3)
print([Link]) # Canis lupus familiaris (attribut de classe)
print([Link]) # Rex (attribut d'instance)
⚙️Les Méthodes — les actions
Les méthodes sont des FONCTIONS définies à l'intérieur d'une classe. Elles définissent ce
que l'objet peut faire.

💡 Astuce Le premier paramètre d'une méthode est toujours 'self'. Il représente l'objet lui-
même. C'est grâce à lui que la méthode peut accéder aux attributs de l'objet.

class Chien:
def __init__(self, nom, age):
[Link] = nom
[Link] = age

def aboyer(self): # méthode simple


print(f"{[Link]} dit : Wouf !")

def anniversaire(self): # modifie un attribut


[Link] += 1 # augmente l'âge de 1
print(f"{[Link]} a maintenant {[Link]} ans !")

def se_presenter(self): # utilise plusieurs attributs


print(f"Je suis {[Link]}, j'ai {[Link]} ans.")

# Utilisation
rex = Chien("Rex", 3)
[Link]() # Rex dit : Wouf !
[Link]() # Rex a maintenant 4 ans !
rex.se_presenter() # Je suis Rex, j'ai 4 ans.
3. L'Encapsulation
L'encapsulation, c'est l'idée de PROTÉGER les données d'un objet. On contrôle qui peut lire
ou modifier les attributs.
💡 Analogie C'est comme un coffre-fort : certaines choses sont accessibles à tous,
d'autres nécessitent une clé, et d'autres encore sont totalement secrètes.

Attributs Public, Protégé et Privé

class CompteBancaire:
def __init__(self, titulaire, solde):

# PUBLIC : accessible partout, pas de préfixe


[Link] = titulaire # tout le monde peut lire

# PROTÉGÉ : un seul underscore '_'


self._banque = "Crédit Général" # convention : usage interne

# PRIVÉ : deux underscores '__'


self.__solde = solde # Python le cache vraiment

compte = CompteBancaire("Alice", 1500)

print([Link]) # ✅ OK : Alice
print(compte._banque) # ⚠️ OK mais déconseillé
print(compte.__solde) # ❌ ERREUR ! AttributeError

Type Syntaxe Accessible depuis Usage

Public nom Partout Données normales

Protégé _nom Classe + sous- Usage interne


classes

Privé __nom Classe uniquement Données sensibles

🔑 Getters et Setters
Les getters et setters sont des méthodes pour LIRE (get) et MODIFIER (set) un attribut privé
de façon contrôlée.

class CompteBancaire:
def __init__(self, solde):
self.__solde = solde # attribut privé

def get_solde(self): # GETTER : lire le solde


return self.__solde

def set_solde(self, nouveau_solde): # SETTER : modifier


if nouveau_solde >= 0: # on vérifie avant d'accepter
self.__solde = nouveau_solde
else:
print("❌ Le solde ne peut pas être négatif !")

compte = CompteBancaire(1000)
print(compte.get_solde()) # 1000
compte.set_solde(1500) # OK
compte.set_solde(-100) # ❌ Le solde ne peut pas être négatif !

✨ @property — la façon moderne (et élégante !)


@property permet d'utiliser un attribut privé COMME S'IL ÉTAIT public, tout en gardant le
contrôle. C'est la méthode recommandée en Python moderne.

class CompteBancaire:
def __init__(self, solde):
self.__solde = solde

@property # décorateur getter


def solde(self):
"""Le solde du compte."""
return self.__solde

@[Link] # décorateur setter


def solde(self, valeur):
if valeur >= 0:
self.__solde = valeur
else:
raise ValueError("Solde négatif interdit !")

compte = CompteBancaire(1000)

# Avec @property, on écrit comme si c'était un attribut public !


print([Link]) # 1000 (pas de parenthèses !)
[Link] = 2000 # OK, appelle le setter automatiquement
[Link] = -50 # ValueError: Solde négatif interdit !
4. L'Héritage
L'héritage permet à une classe ENFANT de récupérer automatiquement tous les attributs et
méthodes d'une classe PARENT. On évite de réécrire du code !
💡 Analogie C'est comme l'héritage familial : tu hérites des yeux de ta mère et du nez de
ton père, mais tu as aussi tes propres caractéristiques uniques.

🌱 Héritage Simple

# CLASSE PARENT (ou classe de base)


class Animal:
def __init__(self, nom, age):
[Link] = nom
[Link] = age

def manger(self):
print(f"{[Link]} mange.")

def dormir(self):
print(f"{[Link]} dort.")

# CLASSE ENFANT : hérite d'Animal


class Chien(Animal): # 'Animal' entre parenthèses = héritage
def __init__(self, nom, age, race):
super().__init__(nom, age) # appelle le constructeur parent
[Link] = race # attribut propre au Chien

def aboyer(self): # méthode propre au Chien


print(f"{[Link]} : Wouf !")

rex = Chien("Rex", 3, "Berger")


[Link]() # ✅ Hérité d'Animal : Rex mange.
[Link]() # ✅ Hérité d'Animal : Rex dort.
[Link]() # ✅ Propre à Chien : Rex : Wouf !
print([Link]) # ✅ Propre à Chien : Berger

🌳 Héritage Multiple
Python supporte l'héritage depuis PLUSIEURS classes à la fois. La classe enfant hérite des
attributs et méthodes de toutes ses classes parents.

class Volant:
def voler(self):
print("Je vole dans les airs !")

class Nageur:
def nager(self):
print("Je nage dans l'eau !")

# Canard hérite de DEUX classes


class Canard(Volant, Nageur):
def coin_coin(self):
print("Coin coin !")
donald = Canard()
[Link]() # Je vole dans les airs !
[Link]() # Je nage dans l'eau !
donald.coin_coin() # Coin coin !

🔗 super() — appeler le parent


super() permet d'appeler une méthode de la classe parent depuis la classe enfant. C'est
indispensable quand on veut enrichir une méthode sans la réécrire entièrement.

class Animal:
def __init__(self, nom):
[Link] = nom
print(f"Animal créé : {[Link]}")

class Chien(Animal):
def __init__(self, nom, race):
super().__init__(nom) # appelle Animal.__init__
[Link] = race # ajoute ce qui est propre au Chien
print(f"Race : {[Link]}")

rex = Chien("Rex", "Berger")


# Résultat :
# Animal créé : Rex
# Race : Berger
5. Le Polymorphisme
Polymorphisme vient du grec et signifie « plusieurs formes ». En POO, cela signifie qu'une
même méthode peut se comporter DIFFÉREMMENT selon l'objet qui l'appelle.
💡 Analogie Le verbe 'parler' est polymorphe : un Français parle en français, un
Espagnol en espagnol, un bébé balbutie. Même action, comportements différents !

🔄 L'Overriding (Redéfinition)
L'overriding consiste à RÉÉCRIRE une méthode héritée dans la classe enfant pour lui
donner un comportement spécifique.

class Animal:
def parler(self):
print("... (son générique)")

class Chien(Animal):
def parler(self): # OVERRIDE de la méthode parent
print("Wouf !")

class Chat(Animal):
def parler(self): # OVERRIDE différent
print("Miaou !")

class Vache(Animal):
def parler(self): # OVERRIDE encore différent
print("Meuh !")

# Le polymorphisme en action !
animaux = [Chien(), Chat(), Vache(), Animal()]
for a in animaux:
[Link]() # Même appel, comportements différents !
# Résultat :
# Wouf ! / Miaou ! / Meuh ! / ... (son générique)

⚡ Overriding vs Overloading
En Python, l'overloading (plusieurs méthodes avec le même nom mais des paramètres
différents, comme en Java ou C++) n'existe PAS directement. Python gère ça différemment.

# En Java (juste pour comprendre la différence) :


# void parler() { ... } # version 1
# void parler(String langue) { ... } # version 2 = OVERLOADING

# En Python, on utilise des paramètres par défaut à la place :


class Chien:
def aboyer(self, fois=1): # paramètre optionnel
print("Wouf ! " * fois)

rex = Chien()
[Link]() # Wouf !
[Link](3) # Wouf ! Wouf ! Wouf !
# Python offre aussi __add__, __mul__, etc. pour surcharger les opérateurs :
class Vecteur:
def __init__(self, x, y):
self.x, self.y = x, y

def __add__(self, autre): # surcharge du +


return Vecteur(self.x + autre.x, self.y + autre.y)

v1 = Vecteur(1, 2)
v2 = Vecteur(3, 4)
v3 = v1 + v2 # appelle __add__ automatiquement !
print(v3.x, v3.y) # 4 6
6. L'Abstraction
L'abstraction consiste à définir une STRUCTURE OBLIGATOIRE que toutes les classes
enfants doivent respecter, sans implémenter le code dans la classe parent.
💡 Analogie C'est comme un formulaire vierge : il définit les cases à remplir (nom,
prénom, âge), mais laisse chaque personne remplir ses propres informations. La
structure est imposée, le contenu varie.

Classe Abstraite avec le module abc


abc signifie Abstract Base Class. Une classe abstraite ne peut pas être instanciée
directement (on ne peut pas créer d'objet depuis elle). Elle sert de modèle.

from abc import ABC, abstractmethod

class Forme(ABC): # hérite d'ABC = classe abstraite


"""Forme géométrique abstraite."""

@abstractmethod # DOIT être redéfinie dans l'enfant


def aire(self):
"""Calcule l'aire de la forme."""
pass # pas d'implémentation ici

@abstractmethod
def perimetre(self):
"""Calcule le périmètre."""
pass

def decrire(self): # méthode normale (non abstraite)


print(f"Aire={[Link]():.2f}, Périmètre={[Link]():.2f}")

# CLASSES CONCRÈTES qui implémentent les méthodes abstraites


class Cercle(Forme):
def __init__(self, rayon):
[Link] = rayon

def aire(self): # OBLIGÉ de définir cette méthode


return 3.14159 * [Link] ** 2

def perimetre(self):
return 2 * 3.14159 * [Link]

class Rectangle(Forme):
def __init__(self, l, h):
self.l, self.h = l, h

def aire(self):
return self.l * self.h

def perimetre(self):
return 2 * (self.l + self.h)

# Utilisation
formes = [Cercle(5), Rectangle(4, 6)]
for f in formes:
[Link]()
# Résultat : Aire=78.54, Périmètre=31.42
# Résultat : Aire=24.00, Périmètre=20.00
# Impossible d'instancier Forme directement !
f = Forme() # ❌ TypeError: Can't instantiate abstract class
7. Les Méthodes Spéciales : __str__, __repr__,
__dict__, __doc__
Python utilise des méthodes spéciales entourées de doubles underscores (appelées dunder
methods) pour définir des comportements spéciaux sur les objets.

📝 __str__ vs __repr__

Ces deux méthodes contrôlent comment un objet s'affiche, mais avec des objectifs différents
:
• __str__ : affichage lisible pour l'utilisateur final (beau et clair)
• __repr__ : affichage technique pour le développeur (doit permettre de recréer l'objet)

class Livre:
def __init__(self, titre, auteur, annee):
[Link] = titre
[Link] = auteur
[Link] = annee

def __str__(self): # pour print() et str()


return f"📚 {[Link]} - {[Link]}"

def __repr__(self): # pour repr() et dans la console


return f"Livre('{[Link]}', '{[Link]}', {[Link]})"

livre = Livre("1984", "Orwell", 1949)

print(str(livre)) # 📚 1984 - Orwell ← lisible


print(repr(livre)) # Livre('1984','Orwell',1949) ← technique
print(livre) # utilise __str__ : 📚 1984 - Orwell

📦 __dict__
__dict__ est un dictionnaire contenant tous les attributs d'instance d'un objet. Très utile pour
débugger ou sérialiser un objet.

class Personne:
def __init__(self, nom, age, ville):
[Link] = nom
[Link] = age
[Link] = ville

alice = Personne("Alice", 25, "Paris")


print(alice.__dict__)
# {'nom': 'Alice', 'age': 25, 'ville': 'Paris'}

# Très utile pour itérer sur les attributs :


for cle, valeur in alice.__dict__.items():
print(f"{cle} : {valeur}")
# nom : Alice
# age : 25
# ville : Paris

📋 __doc__
__doc__ contient la documentation (docstring) d'une classe ou méthode. C'est la chaîne de
texte écrite entre triples guillemets juste après la définition.

class Voiture:
"""
Représente une voiture.
Attributs: marque, modele, annee
"""
def __init__(self, marque, modele):
[Link] = marque
[Link] = modele

def demarrer(self):
"""Démarre le moteur de la voiture."""
print("Vroom !")

print(Voiture.__doc__)
# Représente une voiture.
# Attributs: marque, modele, annee

print([Link].__doc__)
# Démarre le moteur de la voiture.

# help() utilise __doc__ pour afficher l'aide complète


help(Voiture) # affiche toute la doc de la classe
8. Le Garbage Collector et le Comptage de
Références
💡 Analogie Imagine que chaque objet est une maison avec des locataires. Tant qu'il y a
au moins un locataire, la maison reste debout. Quand tous les locataires partent
(références = 0), Python démolît la maison et libère le terrain (mémoire).

🔢 Le Comptage de Références
Python garde un compteur pour chaque objet : combien de variables y font référence.
Quand ce compteur tombe à 0, l'objet est supprimé automatiquement.

import sys # module pour obtenir le compteur de références

class MonObjet:
def __del__(self): # appelé quand l'objet est détruit
print(" Objet détruit !")

# Créer un objet : compteur = 1


a = MonObjet()
print([Link](a)) # 2 (a + l'argument de getrefcount)

# Ajouter une référence : compteur = 2


b = a # b pointe vers le MÊME objet
print([Link](a)) # 3

# Supprimer une référence


del b # compteur redescend à 2
del a # compteur = 0 → objet détruit !
# Objet détruit !

♻️Le Garbage Collector


Le Garbage Collector (GC) s'occupe des cas plus complexes : les références circulaires.
C'est quand deux objets se pointent mutuellement, créant un cycle qui empêche le compteur
de tomber à 0.

import gc # module Garbage Collector

class Noeud:
def __init__(self, valeur):
[Link] = valeur
[Link] = None # pointeur vers un autre noeud

# Créer une référence circulaire


noeud1 = Noeud(1)
noeud2 = Noeud(2)
[Link] = noeud2 # noeud1 → noeud2
[Link] = noeud1 # noeud2 → noeud1 (cycle !)

del noeud1, noeud2 # compteurs ≠ 0 à cause du cycle


# Sans GC : fuite mémoire !
[Link]() # le GC détecte et nettoie le cycle
print("Mémoire nettoyée ✅")

# Info : le GC tourne automatiquement en arrière-plan


print([Link]()) # True → activé par défaut

Mécanisme Rôle

Comptage de références Principal mécanisme : supprime un objet dès que son compteur
atteint 0

Garbage Collector (gc) Mécanisme secondaire : gère les références circulaires que le
comptage ne peut pas détecter

__del__ Méthode appelée automatiquement juste avant la destruction


d'un objet
✅ Résumé Global — Les Piliers de la POO

Concept Mot-clé Python En une phrase


Classe class NomClasse: Le moule qui définit structure et comportement

Objet obj = MaClasse() Une instance concrète créée depuis une classe

Attribut [Link] = valeur Une donnée stockée dans l'objet

Méthode def Une fonction définie dans une classe


ma_methode(self):

Encapsulation _ ou __ + Protéger les données et contrôler l'accès


@property

Héritage class Une classe récupère les attributs/méthodes d'une autre


Enfant(Parent):

super() super().__init__() Appeler le constructeur ou une méthode du parent

Polymorphisme def methode() dans Même nom de méthode, comportements différents


l'enfant

Abstraction from abc import Imposer une structure sans implémenter le code
ABC

__str__ def __str__(self): Affichage lisible pour print()

__repr__ def Affichage technique pour le développeur


__repr__(self):

__dict__ objet.__dict__ Dictionnaire de tous les attributs d'instance

GC import gc / del Libère automatiquement la mémoire inutilisée

🎯 La POO c'est une façon de PENSER le code : au lieu de fonctions qui manipulent
des données séparées, tu crées des OBJETS autonomes qui regroupent données et
comportements. Cela rend le code plus organisé, réutilisable, et facile à faire
évoluer.

Félicitations ! Tu maîtrises maintenant tous les concepts fondamentaux de la POO en


Python. 🎉

Vous aimerez peut-être aussi