Blog ENI : Toute la veille numérique !
🎁 Jusqu'au 25/12 : 1 commande de contenus en ligne
= 1 chance de gagner un cadeau*. Cliquez ici
🎁 Jusqu'au 31/12, recevez notre
offre d'abonnement à la Bibliothèque Numérique. Cliquez ici
  1. Livres et vidéos
  2. Scripting Python sous Linux
  3. Le côté Objet de Python
Extrait - Scripting Python sous Linux Développez vos outils système (2e édition)
Extraits du livre
Scripting Python sous Linux Développez vos outils système (2e édition)
3 avis
Revenir à la page d'achat du livre

Le côté Objet de Python

Introduction

Le chapitre précédent explique que le langage Python s’utilise simplement comme n’importe quel autre langage, à savoir une suite d’instructions, éventuellement regroupées en fonctions, pour faire faire ce que vous voulez à votre ordinateur.

C’est ce que l’on appelle communément la programmation procédurale ou fonctionnelle.

Même si cette technique continuera encore longtemps d’être utilisée, il existe une autre manière de voir les choses et celle-ci ouvre tout un univers parallèle de possibilités :

la programmation orientée objet (POO)

La POO

Avec la programmation procédurale, le traitement à effectuer est divisé en fonctions, avec des données locales ou globales, et le tout donne une procédure qui doit s’exécuter étape par étape.

La POO va plutôt chercher à définir des briques logicielles (les objets) ainsi que la manière dont ils se comportent.

Chaque objet a la responsabilité de tâches et de données spécifiques, et c’est par l’interaction des objets entre eux que le traitement s’effectue.

Ainsi, pour déclencher une action, il faut transmettre un message à l’objet responsable de l’action avec toutes les informations nécessaires pour la réalisation de celle-ci.

Exemple

Chapitre12.Imprime(page=1)     # Impression de la page 1 de l'objet Chapitre12 

Le but est de virtualiser des éléments bien réels et de simuler un modèle restreint de l’univers.

Cela nécessite de modifier sa manière de réfléchir, mais à l’usage, c’est beaucoup plus intuitif.

Pour l’instant, cela peut paraître abstrait, c’est pour cette raison qu’il est nécessaire de définir un peu la matière première de la POO : l’objet.

L’objet

Un objet, au sens informatique du terme, c’est comme n’importe quelle entité en informatique : une référence vers une allocation de la mémoire vive.

Mais un objet en POO, c’est beaucoup plus qu’une simple variable ou une fonction.

Un objet regroupe des valeurs et des fonctions.

Ces valeurs et fonctions constituent la structure de l’objet et sont nommées pour les différencier.

Un point important : un objet est unique, car sérialisé par le processus de création. Ceci sera détaillé plus loin.

En POO, pour faire la différence avec la programmation « traditionnelle procédurale », on parlera plutôt de méthodes pour les fonctions et de propriétés ou d’attributs pour les variables.

Toutefois, ci-après, nous parlerons indifféremment de fonction ou de méthode, tout en sachant qu’une méthode est une fonction liée à un objet ou à une classe.

Autre point : en POO, pour faciliter le processus de création d’objets, on commence par décrire la matrice dans laquelle ils seront créés, à savoir la « classe ».

La classe

La classe décrit les propriétés et les méthodes propres aux objets ; elle sert de modèle pour créer des objets.

Le terme exact pour la création d’objets en POO se nomme « l’instanciation ».

Retenez bien ce point important : tous les objets sont les instances d’une classe.

Ainsi, pour aborder la POO, on commence par décrire une classe, puis on instancie. 

Le résultat donne des objets que l’on peut utiliser pour programmer.

Une classe simple

Pour créer une classe, il faut utiliser l’instruction class avec la syntaxe suivante :

class NomDeLaClasse : 
      bloc de code 

L’instruction class est suivie du caractère deux points (’ :’) et, comme pour tout bloc de code Python, celui-ci est défini par son indentation.

Par convention, mais rien d’obligatoire, le nom des classes est en minuscule, sauf pour la première lettre de chaque mot.

Exemple

LeNomDeCetteClasseEstCorrect, MaClasse, MyClass... 

Voici comment créer avec le langage Python la classe la plus simple qui soit.

Lancez votre terminal préféré puis la ligne de commandes Python, et tapez les lignes suivantes :

class ClasseSimple: 
 pass 

Et c’est tout !

On obtiendra la session :

Python 3.7.3 (default, Apr 30 2019, 16:55:18) 
[GCC 5.4.0 20160609] on linux 
Type "help", "copyright", "credits" or "license" for more information. 
>>> class ClasseSimple: 
...   pass 
... 
>>> 

L’instruction pass ne fait… rien.

Cette instruction très pratique est couramment utilisée pour créer des classes ou des fonctions minimalistes que l’on peut compléter plus tard.

C’est une classe vide, mais c’est une vraie classe, que l’on peut étudier et surtout instancier.

Pour cela,   il suffit d’appeler la classe comme une fonction.

Exemple

NomDeLaClasse() 

Voici comment créer un objet en Python à partir de notre classe « simple » :

>>> mon_objet = ClasseSimple() 

Derrière cette simplicité se cache le processus suivant :

  • création d’une référence nommée « mon_objet » ;

  • appel du constructeur de la classe ;

  • en retour, un pointeur vers le nouvel objet qui sera affecté à la référence mon_objet.

En POO, le constructeur est la fonction spéciale appelée lors de l’instanciation de l’objet ; elle se nomme __new__ en Python....

Ajoutons des attributs

Voyons maintenant comment étoffer nos classes avec des propriétés.

Nous avons évoqué plus haut la notion de constructeur. Celui-ci, en POO, est chargé d’allouer la mémoire pour l’objet à créer et d’initialiser ses attributs.

Pour Python, il existe deux fonctions spéciales bien distinctes : __new__ et __init__.

Pourquoi des doubles underscores sur le nom de ces fonctions ?

En Python, par convention, le double underscore signifie qu’il s’agit d’une méthode « spéciale » réservée au langage Python.

Du fait de son importance, seule la fonction __init__ sera détaillée ici, la fonction __new__ le sera dans un autre chapitre.

Dans tous les cas, il s’agit de fonctions comme les autres, même si elles n’existent que dans le contexte de la classe.

Voici la syntaxe de la fonction __init__ :

class <NomDeLaClasse>: 
   def __init__(<identifiant>): 
       <déclarations> 

Explication :

On définit une classe.

Puis vient la méthode __init__, qui déclare obligatoirement un paramètre pour désigner l’instance de la classe.

Ce paramètre, généralement nommé self, est une référence qu’il est nécessaire de déclarer...

Un premier script « objet »

Reprenons notre classe Document dans un script nommé Document.py.

Vous conviendrez qu’il est plus simple de créer un fichier en concordance avec le nom de la classe, même si ce n’est pas obligatoire.

Prenons comme base de travail l’exemple ci-dessous :

## 
## déclaration de la classe 
## 
class Document: 
   def __init__(self): 
       self.titre = "" 
       self.auteur = "" 
       self.date_mise_a_jour = None 
       self.contenu = [] 
## 
## pour tester la classe 
## 
if __name__ == '__main__': 
   A = Document() 
   print(A)  

Dans ce script, on décrit une classe (Document) avec des attributs (titre, auteur, date_mise_a_jour et contenu) initialisés dans la fonction __init__.

Ensuite, on effectue un test sur la variable __name__ ; cette variable spéciale contient le nom du script courant.

Si le script courant est le script principal, alors __name__ est égale à la valeur ‘__main__’.

Cela signifie que l’on exécute le script principal (Document.py) ; dans ce cas, on peut exécuter les instructions de test de la classe Document.

Ce test, dans le cas présent, consiste à créer...

La surcharge de fonction

En fait, quand dans une classe on déclare une fonction spéciale __str__ ou __init__, on "surcharge" la fonction en question.

En POO, surcharger une fonction signifie déclarer une fonction de l’objet « parent » dans l’objet « enfant ».

Comme dans la vraie vie, les objets ont un parent.

Ainsi, l’objet enfant utilise la fonction de sa classe et non plus celle de la classe « parent ».

Les classes « filles » héritent des propriétés et méthodes de leurs classes « mères ».

Ce mécanisme se nomme « l’héritage » et celui-ci fait partie des concepts fondamentaux de la POO.

L’héritage

En décrivant une classe, on définit des méthodes et des propriétés, puis on instancie. 

Mais on ne part pas de rien :tous les objets créés avec Python sont issus de la classe object. Et lors de l’instanciation, tous les objets héritent des attributs et des méthodes de cette classe.

Ce concept se nomme l’héritage, il est un des piliers de la puissance de la POO.

En POO, il est possible d’inclure dans une classe les propriétés et les méthodes d’une autre, la finalité étant de créer une hiérarchie de classes et de spécialiser les classes à chaque niveau.

Grâce à ce concept, nous pouvons créer des classes, instancier des objets et réutiliser ces classes par le biais de l’héritage.

Cela nous permet d’enrichir les classes filles en redéfinissant (surcharge) des fonctions ou en ajoutant des attributs, et ainsi d’obtenir le comportement voulu.

Voici la syntaxe de l’héritage en Python :

class NomDeLaClasse( classe parent [, autre classe parent  ...] ) 

Comme vous pouvez le remarquer, en Python, l’héritage peut être multiple. Ce concept est détaillé plus loin.

Quand on tape dans l’interpréteur :

>>> class Vide: 
...   pass 
... 

cela revient à...

Exemples de scripts

Il est temps de mettre tout cela en pratique.

Ce schéma illustre ce que nous allons faire en exemple :

images/07EI01.png

À partir d’une classe document générique et grâce au concept de l’héritage et de surcharge, nous allons créer d’autres classes avec des fonctionnements spécifiques. 

Scénario :

Suite à la mise en place d’un nouveau système de contrôle qualité, on nous demande de générer chaque semaine le résultat des sauvegardes des trois environnements PRODUCTION, RECETTE, DEV_TEST sous forme d’un document papier pour archivage dans un classeur.

Exemple du rapport

RESULTAT DES SAUVEGARDES  
------------------------ 
 
Date             PROD        RECETTE    DEV & TEST 
---------------------------------------------------------- 
Lundi             OK            OK            OK 
Mardi             OK            OK            OK 
Mercredi          OK            OK            OK 
Jeudi             OK            OK            OK 
Vendredi          OK            OK            OK 
 
Document créé le <date> par <auteur> 

Analysons la demande.

Il s’agit de produire un document contenant des informations :

  • Un titre

  • Un contenu variable

  • Un pied de page avec la date et l’auteur

Et ce document, nous voulons l’imprimer.

Résultat de l’analyse :

  • => L’objet : un document

  • => Ses attributs : titre, contenu, horodatage et auteur

  • => Une méthode : print

Ceci nous permet d’illustrer la « manière de penser objet ». Nous n’allons pas nous attarder sur le type précis des données que nous manipulons, mais beaucoup plus sur la modélisation des objets, en partant du besoin, et sur les interactions des objets....

Résumé

Ce chapitre vous a présenté les concepts de base de la POO en langage Python.

Python offre des types de base puissants et souples, lesquels vous permettent de construire des briques logicielles tout en conservant la lisibilité et la simplicité de ce langage.

La POO vous apporte l’héritage, qui permet de réutiliser des classes pour en créer d’autres, plus spécialisées et adaptées aux besoins.

Même si « penser objet » peut paraître encore un peu flou, vous devez commencer à apercevoir les possibilités offertes par la POO.

Il reste cependant encore quelques notions plus avancées à découvrir, mais aussi quelques bases à approfondir.

De plus, Python vient avec une énorme bibliothèque de modules qu’il est nécessaire de connaître pour ne pas réinventer la roue à chaque script ; c’est justement le sujet du chapitre suivant.