💡 Python & la POO#

Orienté objet

Les langage de programmation orienté objet implémentent le paradigme de programmation orientée objet (POO). Ce paradigme consiste en la réunion des données et des traitements associées à ces données au sein d’entités cohérentes appelées objets.

Indication

Une introduction plus générale sur la programmation orientée object est disponible ici : 🧩 OOP

Langages à classes ou à prototypes#

Là où les choses se compliquent, c’est que tous les langages objets ne permettent pas de créer et manipuler des classes.

En effet, il existe deux types de langages objet :

  1. Les langages objets à classes

  2. Les langages objets à prototypes

Les langages objets à prototypes (comme par exemple Javascript) ne permettent pas nativement de créer des classes, même s’il manipulent des objets. Les objets y sont créés suivant un prototype (un autre objet) plutôt que par instanciation d’une classe.

Python est un langage orienté objet qui a deux caractéristiques importantes :

  1. Il s’agit d’un langage à classes, son approche orientée objet est dite « traditionnelle », elle s’apparente de celle de C++, en différenciant les concepts de classe et d’objet.

  2. Le développeur n’est pas obligé d’employer une approche objet quand il écrit du code Python.

Important

Python est « multi-paradigme », c’est à dire qu’il autorise plusieurs façon de développer et de concevoir ses programmes. L’une d’entre elle est la programmation orientée object, bien que Python n’impose pas de coder en OOP son fonctionnement interne est fortement teinté d’objet.

Tout est un object#

En python, tout est un object, il suffit d’exécuter ce script pour s’en rendre compte:

print(type(42))
print(type("HelloWorld"))
print(type([]))
print(type(()))
print(type({}))

def func(var):
   print(var)

print(type(func))

et nous obtiendrons cette sortie:

<class 'int'>
<class 'str'>
<class 'list'>
<class 'tuple'>
<class 'dict'>
<class 'function'>

Ces éléments sont tous de types différent mais ont un point en commun le terme class. A l’instar de l’instruction def qui définit une fonction, class définit une classe d’object python.

Définir ses propres objets#

Nous allons traduire la classe définit au format UML

https://www.plantuml.com/plantuml/svg/JOwn2W9134JxV4LAHR0GRAok4B7o5oItkzujjvj8aiL2_7SN577AcJVC3EQatch1c5cCcbvhybcYWGKg2NVRFTYI-KvA5KSAowJIE0OfekXAR3rAx7zKJ3TgnK_2Vg6QyDnR0A6G6Hw_C_W4xDfm1mvehfad-5YFMQZcrVfdlm26nB6_V0C=

Diagramme UML de notre classe dinosaure#

Notre première classe en python#
class Dinosaur(object):

   def __init__(self, name: str):
      self.name = name

   def whoami(self) -> str:
      return f"I'm {self.name}"

Quelques remarques:

  • le mot clé class définit notre classe d’object, par convention son nom commence par une majuscule.

  • notre classe définit deux méthodes.

  • __init__ est l’initialisateur de notre classe et permet de définir les attributs de notre instance.

Important

Toute méthode d’instance doit prendre en premier paramètre la référence vers l’instance via le mot clé self

Classe et instance#

Une classe est un « blueprint » qui nous permet de créer des objet, elle définit ses attributs et méthodes. Pour créer une instance il faut l’instancier:

rexy = Dinosaur('Rexy')
clever_girl = Dinosaur('Clever Girl')

print(type(rexy))
print(type(clever_girl))

Nous avons créer deux instances de notre classe Dinosaur, celles-ci sont autonomes, il s’agit de deux object bien distincts.

Attributs#

Un attribut est une donnée associé à un object, celui-ci peut contenir n’importe quel object python.

Accéder aux attributs#
print(rexy.name)
print(clever_girl.name)
Modifier un attribut#
clever_girl.name = 'The Big One'

print(clever_girl.name)
Ajouter un attribut#
clever_girl.specie = 'Velociraptor'

print(clever_girl.specie)

Important

Tous les attributs et méthodes des classes Python sont « publics » au sens de C++.

We are all consenting adults

—Guido van Rossum, (Créateur de Python).

La convention de préfixer un attribut et/ou une méthode par _ indique qu’il s’agit d’un attribut interne et d’éviter de l’utiliser.

Méthodes#

Une méhode est une « fonction associé à un object », elle peut utiliser ses attributs, les modifier et faire appels à d’autres méthodes de l’object.

Attention

Toutes les méthodes prennent une variable self (sauf les méthodes de classe) comme premier argument. Cette variable est une référence à l’objet manipulé.

Appel à une méthode#
print(rexy.whoami())

Indication

On ne spécifie pas le paramètre self lorsque l’on manipule une instance. Le lien entre l’instance et la méthode est déjà fait.

La méthode __init__#

La méthode __init__ est comme son nom l’indique un initialisateur, l’instance de notre classe est déjà créer à ce moment là.

En Python, on n’est pas tenu de déclarer tous les attributs de la classe comme dans d’autres langages : on peut se contenter de les initialiser au sein de la méthode __init__ !

Héritage#

Python supporte l’héritage simple et l’héritage multiple. La création d’une classe fille est relativement simple, il suffit de préciser entre parenthèses le nom de la classe mère lors de la déclaration de sa fille.

class Sauropod(Dinosaur):

    def __init__(self, name):
        super(Sauropod, self).__init__(**kwargs)
        self.family = "Sauropod"

Note

Un élément important à remarquer est l’utilisation de la fonction super(), elle permet, de manière « intelligente », de déléguer à la ou les classe(s) mère(s) l’exécution de certains traitements.

On l’utilise donc notamment pour appeler, depuis une classe fille, le constructeur de la classe mère.

La méthode super() utilise l’algorithme du MRO (Method Resolution Order) pour parcourir l’arbre des héritages.