Introduction
Ce tutoriel est une introduction aux concepts de la programmation orientée objet. Il fournit des explications concises, illustrées avec des exemples de code en Python.
Ce tutoriel est destiné aux personnes qui :
- Connaissent déjà les concepts de classes et d'objets appliqués dans d'autres langages et qui souhaitent être opérationnelles rapidement en Python.
- Ne connaissent pas les objets et qui souhaitent apprendre de façon simple et rapide (sans nécessairement voir tous les aspects théoriques de la programmation orientée objet).
Ce tutoriel n'est pas déstiné aux personnes qui :
- souhaitent apprendre les concepts avancés de Python ou connaître les détails du fonctionnement de Python.
Si vous connaissez déjà le concept d'objets, vous pouvez passer l'introduction.
Qu'est-ce qu'un objet ?
Créer un objet revient à créer une structure de donnée (un type) à part entière.
Un objet peut contenir plusieurs variables (appelées attributs ou propriétés) qui permettent de stocker les données associées à un objet. Un objet peut aussi contenir un ensemble de fonctions qui lui sont rattachées (appelées méthodes) et qui permettent de manipuler les propriétés de l'objet.
Il est possible de créer plusieurs objets d'un même type (qu'on appellera une classe) et chacun de ces objets pourra avoir des valeurs différentes pour ses propriétés.
Si, par exemple, on développe un programme bancaire, on pourra créer un objet pour chacun des comptes utilisateurs. Ainsi, chaque utilisateur aurait un objet correspondant avec les informations qui lui sont rattachées.
objet_compte1 = CompteBancaire() # On crée deux objets objet_compte2 = CompteBancaire() print(objet_compte1.nom) # On affiche le nom du compte 1 print(objet_compte1.solde)# On affiche le solde du compte 1 print(objet_compte2.nom) # Là, on affiche le nom du deuxième compte print(objet_compte2.solde)# Là, on affiche le solde du deuxième compte
Les deux objets qu'on a créé appartiennent à la même classe, ils possèdent donc la même structure avec les mêmes propriétés mais celles-ci ont des valeurs différentes.
Les objets disposent également de fonctions (méthodes) qui leur sont rattachées.
objet_compte1.effectuerRetrait(100) objet_compte2.effectuerDépôt(300)
Les attributs et les méthodes d'un objet sont définis dans la définition de sa classe.
La programmation orientée objet (POO en français ou OOP en anglais) est une méthode de programmation qui vise à manipuler les objets afin de mieux résoudre certains problèmes.
Créer une classe avec des méthodes et des propriétés :
class CompteBancaire: """ Classe représentant un compte bancaire""" # une variable partagée par tous les objets de cette classe type = 'Compte normal' def __init__(self, nom): # variables par défaut, uniques pour chque objet : self.nom = nom self.solde = 0.0 # Méthodes de l'objet : def afficherSolde(self): print self.solde return def effectuerRetrait(self, montant): self.solde -= montant return def effectuerDépôt(self, montant): self.solde += montant return
La méthode spéciale __init__()
est appelée automatiquement lorsqu'un objet est créé.
Il est possible de lui passer des arguments qui seront utilisés pour initialiser l'objet créé avec certaines valeurs.
Créer un objet avec une classe et l'utiliser
objet1 = CompteBancaire("J1") # on crée une nouvelle instance # avec le nom de la classe objet2 = CompteBancaire("P2") # on crée une deuxième instance # on utilise leurs propriétés print(objet1.nom) #'J1' print(objet2.nom) #'P2' # Accéder aux méthodes d'un objet objet1.effectuerDépôt(100) objet2.effectuerDépôt(200) print(objet1.solde) # 'J1' print(objet2.solde) # 'P2' # instructions équivalentes à : objet1.afficherSolde() # 100 objet2.afficherSole() # 200 print(objet1.type) # 'Compte normal' print(objet2.type) # 'Compte normal'
Il est possible de déclarer une nouvelle propriété sur un seul des objets en affectant une valeur à une propriété choisie. Il est possible de supprimer une propriété d'un objet en utilisant del
:
objet1.code_réduction = 'secret' print(objet1.code_réduction) # 'secret' print(objet2.code_réduction) # déclenche une erreur AttributeError: objet2 instance has no attribute 'code_réduction' del objet1.discount_code # on remet dans son état précédent
Un peu de théorie
Vous réaliserez rapidement qu'en Python, tout est un objet. Cela signifie que tout ce que vous manipulez en Python a une classe. Pour déterminer la classe d'un objet, vous pouvez utiliser la propriété par défaut __class__
:
compte3 = CompteBancaire() print(compte3.__class__) # __main__.CompteBancaire string = 'Chat' print(string.__class__) # <type 'str'>
Dans un précédent article, on a vu [1,2].reverse()
et effectivement, reverse()
est une méthode de la classe native 'list' qui permet de représenter les listes.
L'héritage
Il est possible de faire « hériter » une classe d'une autre. Ainsi, la classe « fille » hérite des attributs et méthodes de la classe « parente » mais on peut également lui ajouter des propriétés et des méthodes qui lui seront propres (seule la classe fille en bénéficiera) :
class CompteProfessionnel( CompteBancaire ): # On « surcharge » l'attribut type = 'Compte professionnel' # On ajoute une fonctionnalité sous la forme d'une méthode def demanderCrédit(self, montant): self.solde += montant pro = CompteProfessionnel()
Lorsqu'on accède aux propriétés d'un objet, l'interpréteur consulte la classe de l'objet. S'il ne trouve pas la propriété, il remonte la « chaîne d'héritage » pour analyser la classe parente et ainsi de suite jusqu'à ce qu'il trouve (ou non) la propriété recherchée.
Il est possible d'utiliser les propriétés originales d'une classe qu'on surcharge en préfixant du nom de la classe :
class CompteProSpécial( CompteProfessionnel ): def demanderCrédit(self, montant): self.solde = CompteProfessionnel.demanderCrédit(self, montant) return
Note : Les méthodes __init__()
ne sont pas héritées.
On peut utiliser la fonction isinstance()
pour vérifier qu'un objet est une instance d'une classe donnée ou d'une de ses sous-classes.
On peut utiliser la fonction issubclass()
afin de vérifier qu'une classe hérite d'une autre classe :
isinstance(pro, CompteProfessionnel) # True isinstance(pro, CompteBancaire) # True, classe héritée issubclass(CompteProSpécial, CompteBancaire) # True
L'héritage multiple
Python permet de créer des classes qui héritent de plusieurs classes à la fois :
class ClassePersonnalisée( CompteProfessionnel, CompteInternational, ComptePrivilège): # . . .
Dans ce cas, si l'interpréteur ne trouve pas une propriété dans la classe de l'objet, il analysera les différentes classes parentes de la gauche vers la droite (dans l'exemple, le parcours commencera donc avec CompteProfessionnel
avant de se poursuivre avec CompteInternational
et ainsi de suite).
Les itérateurs
Comme nous l'avons déjà vu dans un article précédent, il est possible d'itérer sur les éléments d'un objet Python avec une boucle for
:
for i in ['a', 'b', 'c']: print(i) # 'a' # 'b' # 'c' for i in 'abc': print(i) # notation identique
La fonction iter()
peut être utilisée avec des objets spécifiques appelées itérateurs :
itérateur = iter('abc') itérateur.next() # 'a' itérateur.next() # 'b' itérateur.next() # 'c'
Pour qu'un objet puisse être parcouru de cette façon, il suffit de définir le comportement de deux méthodes __iter__()
et next()
:
class CompteItérable( CompteBancaire ): def __init__(self, nom): self.nom = nom self.index = len(self.nom) def __iter__(self): return self def next(self): # l'itérateur parcourera le nom # dans l'ordre inverse if self.index == 0: raise StopIteration self.index -= 1 return self.nom[self.index] itérable = CompteItérable('pile') for i in itérable: print(i) # 'e' # 'l' # 'i' # 'p'