texte = "dakar"
print(texte.upper())
notes = [17, 12]
notes.append(15)
print(notes)DAKAR
[17, 12, 15]
DMI · FST · UCAD
Jusqu’ici, les données (variables) et les traitements (fonctions) étaient séparés. La programmation orientée objet les réunit : un objet regroupe des données et les comportements qui vont avec. Cette séance construit ses propres objets avec class, puis les spécialise par héritage et polymorphisme. Exécutez chaque cellule avec Maj + Entrée. Les cellules À vous sont à compléter.
Une chaîne, une liste sont déjà des objets : ils portent des données (leur contenu) et des méthodes (des fonctions attachées, appelées avec un point). "dakar".upper() et notes.append(15) sont des méthodes d’objets que vous employez depuis le début.
DAKAR
[17, 12, 15]
À vous. Avec mot = "SENEGAL", affichez sa version en minuscules grâce à la méthode .lower().
Une méthode peut aussi renvoyer un résultat. "Dakar-Thies-Mbour".split("-") renvoie une liste.
['Dakar', 'Thies', 'Mbour']
3
À vous. Découpez la chaîne "Astou;Modou;Bineta" sur le ";" avec .split(";") et affichez la liste obtenue.
L’idée de la POO est d’écrire nos propres types d’objets, adaptés à notre problème — un compte bancaire, un patient, un produit — avec leurs données et leurs méthodes.
Une classe est le plan d’un objet : elle décrit ses données et ses méthodes. On la définit avec class. La méthode spéciale __init__ est le constructeur : elle s’exécute à la création et installe les données de l’objet. Le premier paramètre, self, désigne l’objet en cours de construction.
Astou
5000
c1 est une instance de la classe CompteBancaire. On accède à ses données (ses attributs) avec un point : c1.titulaire, c1.solde. Chaque instance possède ses propres valeurs.
Astou 5000
Modou 12000
À vous. Créez une instance c3 de CompteBancaire pour le titulaire "Bineta" avec un solde de 8000, puis affichez son titulaire et son solde.
Un attribut se lit, mais se modifie aussi directement avec un point.
À vous. Modifiez le solde de c3 pour le porter à 9500, puis affichez-le.
Une méthode est une fonction définie dans la classe : c’est un comportement de l’objet. Elle reçoit toujours self en premier paramètre, ce qui lui permet de lire et de modifier les attributs. Ici, depot et retrait modifient le solde ; peut_retirer renvoie un booléen.
class CompteBancaire:
def __init__(self, titulaire, solde):
self.titulaire = titulaire
self.solde = solde
def depot(self, montant):
self.solde = self.solde + montant
def retrait(self, montant):
if montant <= self.solde:
self.solde = self.solde - montant
else:
print("Solde insuffisant")
def peut_retirer(self, montant):
return montant <= self.solde
c1 = CompteBancaire("Astou", 5000)
c1.depot(2000)
print(c1.solde)
c1.retrait(1000)
print(c1.solde)7000
6000
On appelle une méthode sur l’objet : c1.depot(2000). Inutile de passer self, Python s’en charge : self sera c1. Si le retrait dépasse le solde, la méthode affiche un message au lieu de l’effectuer.
La méthode peut_retirer ne modifie rien : elle renvoie True ou False, qu’on peut utiliser dans un test.
À vous. Créez un compte c4 pour "Modou" avec 3000, effectuez un dépôt de 1500, puis affichez son solde.
__str__Par défaut, print(objet) donne une ligne peu lisible. La méthode spéciale __str__ décide ce qui s’affiche : elle doit renvoyer une chaîne, et print l’utilise automatiquement. On ajoute aussi une méthode description qui renvoie un libellé — elle nous servira plus loin.
class CompteBancaire:
def __init__(self, titulaire, solde):
self.titulaire = titulaire
self.solde = solde
def depot(self, montant):
self.solde = self.solde + montant
def retrait(self, montant):
if montant <= self.solde:
self.solde = self.solde - montant
else:
print("Solde insuffisant")
def peut_retirer(self, montant):
return montant <= self.solde
def __str__(self):
return f"Compte de {self.titulaire} : {self.solde} F"
def description(self):
return "compte courant"
c1 = CompteBancaire("Astou", 5000)
print(c1)
c1.depot(2000)
print(c1)
print(c1.description())Compte de Astou : 5000 F
Compte de Astou : 7000 F
compte courant
À vous. Créez un compte pour "Bineta" avec 9000 et affichez-le directement avec print.
L’héritage crée une classe à partir d’une autre : elle récupère tout (attributs et méthodes) et peut ajouter ce qui lui est propre. CompteEpargne(CompteBancaire) se lit « un compte épargne est un compte bancaire, en plus spécialisé ». super().__init__(...) appelle le constructeur du parent pour ne pas réécrire l’installation des données communes.
class CompteEpargne(CompteBancaire):
def __init__(self, titulaire, solde, taux):
super().__init__(titulaire, solde)
self.taux = taux
def ajouter_interets(self):
self.solde = self.solde + self.solde * self.taux
e1 = CompteEpargne("Bineta", 10000, 0.05)
print(e1)
e1.depot(5000)
e1.ajouter_interets()
print(e1.solde)Compte de Bineta : 10000 F
15750.0
e1 profite de tout CompteBancaire : print(e1) utilise le __str__ hérité, et e1.depot(5000) la méthode depot héritée. ajouter_interets et l’attribut taux lui sont propres. Après le dépôt (solde 15000), les intérêts à 5 % portent le solde à 15750.
À vous. Créez un compte épargne e2 pour "Modou" avec 20000 et un taux de 0.03, appliquez ajouter_interets(), puis affichez son solde.
Redéfinir dans la classe fille une méthode du parent s’appelle surcharger. Le polymorphisme en découle : un même appel produit un résultat différent selon le type réel de l’objet. On surcharge description dans CompteEpargne, puis on parcourt une liste mélangée.
class CompteEpargne(CompteBancaire):
def __init__(self, titulaire, solde, taux):
super().__init__(titulaire, solde)
self.taux = taux
def ajouter_interets(self):
self.solde = self.solde + self.solde * self.taux
def description(self):
return f"compte epargne a {self.taux}"
comptes = [CompteBancaire("Astou", 5000), CompteEpargne("Bineta", 10000, 0.05)]
for c in comptes:
print(c.titulaire, ":", c.description())Astou : compte courant
Bineta : compte epargne a 0.05
La boucle appelle exactement le même c.description() à chaque tour, mais Python choisit la version qui correspond au type réel de l’objet : « compte courant » pour l’un, « compte epargne » pour l’autre. C’est le polymorphisme.
À vous. Construisez une liste mes_comptes contenant un CompteBancaire et un CompteEpargne de votre choix, puis affichez la description() de chacun avec une boucle for.
Le polymorphisme fonctionne aussi à travers une fonction : elle accepte n’importe quel compte et appelle description(), sans se soucier du type exact.
Il s'agit d'un compte courant
Il s'agit d'un compte epargne a 0.05
À vous. Écrivez une fonction resume(compte) qui affiche le titulaire suivi de la description du compte, puis appelez-la sur comptes[0] et comptes[1].
self : toute méthode prend self en premier paramètre, et l’on écrit self.attribut pour accéder aux données de l’objet. L’oubli provoque une erreur.CompteBancaire est le plan ; c1 = CompteBancaire(...) est un objet concret. Les méthodes s’appellent sur l’instance.c1.description seul ne fait rien (il désigne la méthode) ; il faut écrire c1.description() pour l’exécuter.class). Instance : un objet concret créé à partir du plan.__init__(self, ...) : le constructeur ; installe les attributs (self.x = ...).self : l’objet courant ; toute méthode le reçoit en premier paramètre.objet.methode(...) ; peut modifier l’objet ou renvoyer une valeur.__str__ : renvoie la chaîne affichée par print(objet).class Fille(Parent) récupère tout et ajoute ; super().__init__(...) réutilise le constructeur parent.Prochaine séance — S6 : NumPy et le calcul sur des tableaux, premier outil de la science des données.