ProPython
Bases de Python - Programmation Orientée Objet
14 Mar, 2021

Bases de Python - Programmation Orientée Objet

Dans cette article, nous allons découvrir les bases de la Programmation Orientée Objet (POO), avec les notions de classe et d'héritage, puis nous allons voir comment implémenter cela en Python.

Définition

La POO est un paradigme de programmation qui consiste à diviser son code en rassemblant des propriétés et des comportements dans des classes afin de former des objets.

Des objets sont comme des composants d'un système complexe. Chaque objet remplit une ou plusieurs fonctions, et la coordination entre ces objets permet de faire fonctionner le programme. Par exemple, si on reprend le jeu de morpion traité dans cet article : Exercice - Jeu de Morpion, on peut diviser le programme en différents objets :

  • Un objet Plateau : correspond au plateau du jeu, et contient des méthodes pour le dessiner, le mettre à jour, etc...
  • Un objet Ordinateur : correspond à l'ordinateur, et contient une méthode pour choisir une case aléatoire du plateau.
  • Un objet Joueur : correspond au joueur, et contient une méthode pour demander sur quelle case jouer.

En fait, la POO est une façon de modéliser le monde réel et les interactions entre les différents éléments, par exemple on peut créer un objet Voiture et modéliser ses interactions avec un objet Parking.

Créer une classe

Une classe est ce qui permet de fabriquer un objet, c'est comme un plan. On dit donc qu'on objet est une instance d'une classe. Imaginons que vous souhaitez modéliser une personne. Il faut donc créer la classe Personne, et ensuite vous pourrez instancier plusieurs personnes, par exemple avec des noms ou des âges différents. Ainsi, Personne est une classe et John est une instance de cette classe.

Pour créer une classe, on utilise la mot-clé class suivi du nom de la classe et de :. Par exemple, pour créer une classe Personne :

class Personne:

Cependant, ce code ne fonctionnera pas en Python car vous ne pouvez pas créer de classe sans déclarer d'attributs. Pour rappel, les attributs sont des variables appartenant à la classe. Dans notre cas, on peut donner un nom, un prénom, un âge, un sexe… à une personne. Pour cela, on a besoin de la méthode spéciale __init__.

La méthode __init__

Comme évoqué plus haut, cette méthode est une méthode spéciale. Pour rappel, une méthode est une fonction appartenant à une classe. Les méthodes spéciales sont des méthodes permettant à un objet d'avoir des comportements particuliers. Ici, la méthode __init__ permet de définir un constructeur pour notre classe, c'est à dire que lorsqu'on créera un objet, la méthode __init__ sera appelée. Cette méthode est générique et c'est la seule méthode permettant de définir un constructeur, donc vous êtes obligés de la coder dans chaque classe que vous réalisez. Comme toute fonction, on peut y passer des paramètres et les utiliser dans le corps de la classe. On peut par exemple lui passer les paramètres nom, prenom, age etc... afin de construire un objet Personne avec ces attributs. Avant d'écrire cette méthode pour notre classe, il est cependant nécessaire de voir le mot-clé self.

Le mot-clé self

Lorsque l'on utilise une instance d'une classe, il est nécessaire de différencier les attributs qui appartiennent à la classe, des paramètres utilisés dans les méthodes. Par exemple, en reprenant l'exemple de la classe Personne, on sait que cette classe possède un attribut nom. Comment je peux accéder à cet attribut depuis l'intérieur de ma classe ? C'est là qu'il faut utiliser le mot-clé self. En utilisant self.nom dans ma classe, je peux accéder à l'attribut nom. Mais pour utiliser ce mot-clé, il est nécessaire de le passer en premier paramètre de la méthode dans laquelle on souhaite l'utiliser. On peut maintenance écrire notre méthode __init__ qui sera donc le constructeur de notre classe Personne.

def __init__(self, nom, prenom, age):
    self.nom = nom
    self.prenom = prenom
    self.age = age

On passe self en premier paramètre afin de pouvoir déclarer nos attributs via self.nom, self.prenom et self.age.

Notre classe Personne ressemble donc à ceci maintenant :

class Personne:

    def __init__(self, nom, prenom, age):
        self.nom = nom
        self.prenom = prenom
        self.age = age

Et on peut donc créer un objet Personne maintenant !

Instancier une classe

Afin d'instancier une classe, il faut utiliser le constructeur défini dans la classe que l'on souhaite instancier. Dans notre exemple, on passe 3 paramètres au constructeur de Personne (en réalité 4, mais self est un paramètre faisant référence à l'objet lui-même). On doit donc forcément passer ces paramètres lorsque l'on instancie une classe Personne. Voici comment créer un objet Personne.

>>> jean = Personne("Dupont", "Jean", 41)
>>> jean
<__main__.Personne object at 0x000001DEC4770040>

Lorsque l'on souhaite afficher notre objet, on obtient une drôle de ligne. C'est l'affichage par défaut de tout objet. Heureusement, il existe une méthode spéciale pour modifier cet affichage. Il s'agit de la méthode __repr__. Elle ne prend aucun paramètre (sauf self afin d'accéder à l'objet que l'on souhaite afficher) et renvoie une chaine de caractères qui est le texte que vous voyez lorsque vous affichez votre objet via l'interpréteur ou la fonction print. Essayez d'implémenter cette fonction dans notre classe Personne, de sorte qu'on obtienne le résultat suivant, c'est un petit entraînement pour voir si vous avez compris ce qu'on a vu jusque là :

>>> jean = Personne("Dupont", "Jean", 41)
>>> jean
Je m'appelle Jean !
Correction

Maintenant que notre objet est créé, on aimerait interagir avec, il faut donc implémenter des méthodes.

Implémenter des méthodes

Normalement, vous savez déjà implémenter des méthodes. En effet, nous avons toute à l'heure implémenté des méthodes spéciales, l'implémentation de méthodes classiques est tout à fait similaire. La seule différence est que l'appel à ces méthodes se fait différemment. Voici la syntaxe : objet.methode(parametre1, parametre2, ...). Par exemple, si on crée une méthode discuter pour notre classe Personne qui prend en paramètre une chaine de caractères, on appellera cette méthode de cette façon :

jean.discuter("Bonjour !")  # jean est une instance de Personne

D'ailleurs, puisque vous savez déjà implémenter des méthodes, vous devriez réussir à implémenter celle-ci dans notre classe Personne, de sorte que l'on obtienne ceci :

>>> jean.discuter("Bonjour")
Jean a dit : 'Bonjour !'
Correction

Maintenant vous savez créer des classes basiques ! Nous pouvons donc attaquer la notion d'héritage.

L'héritage

Définition

L'héritage est une notion fondamentale de la Programmation Orientée Objet, permettant de créer une nouvelle classe en se basant sur une classe existante. Cela permet de spécialiser une classe existante sans avoir à tout réécrire. Cela permet aussi la création de classes abstraites dont nous parlerons plus tard.

Pour comprendre la notion d'héritage, reprenons notre classe Personne. Elle modélise une personne, sans réelle spécificité. Et si nous souhaitons modéliser un employé par exemple. Un employé est d'un point de vue POO une spécialisation d'une personne, puisqu'il a, en plus des attributs d'une personne, un salaire, et une entreprise pour laquelle il travaille. Le mieux à faire est donc de faire hériter notre classe Employe de la classe Personne, ainsi notre nouvelle classe aura accès aux attributs et méthodes de la classe Personne appelée classe parente, et on pourra même définir de nouveaux attributs et de nouvelles méthodes spécifiques à notre classe Employe, c'est ce que nous allons faire maintenant !

Implémentation en Python

Pour créer une classe héritant d'une autre classe en Python, on le précise lors de la définition de la classe de cette façon :

class nom_classe(nom_classe_parente):

On précise entre parenthèses la classe parente.

Appliqué à notre exemple, ce code devient :

classe Employe(Personne):

Maintenant, il faut définir un constructeur. En effet, vous vous rappelez, je vous ai dit que pour toute classe il faut définir un constructeur, cela est valable aussi pour les classes héritant d'autres classes. On aurait pu penser que s'il n'y a pas de constructeur, on prend celui par défaut de la classe parente, mais ce n'est pas le cas en Python !

Dans notre exemple, un employé est une personne, possédant en plus un salaire et une entreprise. On peut donc utiliser le constructeur de la classe Personne, et y rajouter deux paramètres pour le salaire et l'entreprise. Pour faire ceci, nous allons avoir besoin de la fonction super.

La fonction super

C'est une fonction très puissante, très utilisée dès qu'on touche à l'héritage, qui permet d'appeler la classe parente.

En effet, en appelant super, on fait référence à la classe parente, et on peut donc récupérer ses méthodes. Par exemple, pour récupérer le constructeur de la classe parente, on utilise super().__init__.

On peut maintenant revenir à notre classe Employe, et écrire notre constructeur.

# classe Employe

def __init__(self, nom, prenom, age, salaire, entreprise):
    super().__init__(nom, prenom, age)
    self.salaire = salaire
    self.entreprise = entreprise

Quelques explications sur ce code : on a besoin maintenant de 5 paramètres dans notre constructeur, puisqu'on définit en plus des attributs de base des attributs pour le salaire et l'entreprise. Ensuite, on appelle le constructeur de la classe parente, en utilisant super. On lui passe les paramètres correspondants, donc nom, prenom et age. Et ensuite on rajoute la déclaration des attributs spécifiques à notre classe Employe.

Redéfinir et rajouter des méthodes

Comme nous l'avons fait pour le constructeur de la classe, nous pouvons redéfinir n'importe quelle méthode, et même en ajouter des nouvelles.

Pour en redéfinir, il suffit de les réécrire, et de modifier leur code. Pour en rajouter, il suffit de définir de nouvelles méthodes. Vous savez déjà tout ! Essayez donc de redéfinir la méthode discuter pour afficher l'entreprise à côté du nom de la personne, et la méthode __repr__ pour afficher en plus le salaire.

Correction

Accéder aux attributs de la classe parente

Pour accéder aux attributs de la classe parente depuis l'intérieur de la classe enfant, vous pouvez soit utiliser simplement self comme pour accéder à n'importe quel attribut déclaré dans la classe enfant, ou alors super, comme pour accéder à une méthode.

Le mot de la fin

Attention, cet article n'est qu'un aperçu de la Programmation Orientée Objet. Il y a beaucoup d'autres choses à savoir, comme les notions d'encapsulation, d'héritage multiple ou de polymorphisme, cependant il constitue une bonne base pour débuter et réaliser des codes simples. Nous verrons plus tard les autres notions évoquées.

Si cet article vous a plus, n'hésitez pas à laisser un commentaire ! Si vous souhaitez vous exprimer ou demander des précisions, vous pouvez me contacter par mail : contact@propython.fr, ou laisser un message via l'onglet Contact visible si vous êtes sur ordinateur.

A très bientôt pour la suite de votre apprentissage du Python !

Laisser un commentaire

Premium - 15€/mois

L'accès à des articles inédits, à une multitude de ressources, à de nouveaux projets, mais également à des vidéos explicatives, découvrez ici pourquoi passer premium.

Articles liés

Catégories

Ressources

Retrouvez une collection de ressources (des scripts, des fiches résumé, des images...) liées aux articles du blog ou au Python.
Voir

Contact

contact@propython.fr
Se connecter pour envoyer un message directement depuis le site.

Navigation

AccueilSe connecterCréer un compteRessourcesPremium

Catégories

Pages légales

Politique de confidentialitéMentions légalesConditions générales de vente