Retourner à : Python pour débutants
Maintenant que nous avons les bases de la programmation en Python, il est temps de faire nos premiers pas dans la programmation orientée objet en Python et d’introduire deux nouveaux concepts : les classes et les objets. L’objectif n’est pas d’entrer dans des notions avancées, mais de comprendre les bases de la programmation orientée objet en Python.
Pour cela, nous allons :
- définir ce que sont les classes et les objets
- créer une classe simple en Python
- créer des objets à partir d’une classe
- définir et utiliser des attributs
- créer et utiliser des méthodes de classes
Définitions
Avant de nous lancer dans l’écriture de code, prenons un instant pour définir les concepts de classes et objets.
Une classe peut être vue comme un plan ou une spécification. Elle décrit la structure et le comportement des objets que nous allons manipuler dans notre programme. De leur côté, les objets, sont des instances concrètes de cette classe.
Si on simplifie énormément, on pourrait considérer une classe, comme étant un plan qui spécifie tous les aspects d’un objet, et un objet est donc un exemplaire concret construit à partir de ce plan. Donc, dans la vraie vie, le plan d’une Renault Clio correspondrait à une classe, tandis que notre Renault Clio et celle de notre voisin seraient deux objets distincts, tous deux basés sur ce même plan.
Création d’une première classe
En Python, une classe se définit à l’aide du mot-clé class, suivi du nom de la classe. Par convention, les noms de classes utilisent le PascalCase, c’est-à-dire que chaque mot commence par une majuscule.
Créons une classe très simple nommée Car :
class Car:
passPour l’instant, cette classe ne contient aucune logique. Le mot-clé pass permet simplement d’indiquer à Python que le bloc est volontairement vide.
Création d’objets (instances)
Une fois la classe définie, nous pouvons créer des objets à partir de celle-ci, en utilisant son nom, suivi de parenthèses :
class Car:
pass
blue_car = Car()
red_car = Car()Nous venons de créer deux objets distincts, qui sont tous les deux des instances de la classe Car.
Maintenant que nous avons nos objets, nous pouvons leur ajouter dynamiquement des attributs. Pour commencer, un attribut est une variable qui est associée (a.k.a. qui appartient) à un objet. Pour notre classe voiture, on pourrait avoir différents attributs, tels que sa couleur, sa taille, sa marque, sa vitesse actuelle, etc…
Pour créer un attribut, on peut utiliser les objets que nous venons de créer à l’instant, suivi d’un point, puis le nom de l’attribut souhaité. Ensuite, il ne nous reste plus qu’à assigner une valeur à cet attribut.
Dans notre exemple, si nous souhaitons rajouter un attribut qui indique la couleur de nos voitures, nous pouvons faire la chose suivante :
class Car:
pass
blue_car = Car()
red_car = Car()
blue_car.color = "blue"
red_car.color = "red"
print(blue_car.color)
print(red_car.color)Si nous exécutons ce code, on voit bien que chaque objet possède sa propre couleur :

En revanche, si nous essayons d’imprimer un attribut qu’on n’a pas assigné au préalable, on reçoit une exception :

Problèmes avec cette approche
Même si cette manière de créer des attributs fonctionne, il pose plusieurs problèmes :
- rien n’indique quels attributs une voiture est censée posséder
- deux objets de la même classe peuvent avoir des attributs différents
- il n’y a aucune garantie qu’un attribut existe avant d’y accéder
Pour éviter cela, nous devons structurer explicitement les données associées à la classe.
Initialisation d’un objet
Python fournit une méthode spéciale appelée __init__, qui est exécutée automatiquement lors de la création d’un objet. Cette méthode permet, entre autres, d’initialiser les attributs de l’objet. La méthode __init__ prend en premier argument le mot-clé self, qui est une référence à l’objet concret créé par la classe.
À l’intérieur de notre __init__, nous pouvons donc assigner des attributs à self afin de définir la structure (a.k.a. les attributs) des objets qui seront créés par notre classe, ainsi que leurs valeurs par défaut :
class Car:
def __init__(self):
self.color = ""
self.brand = ""
self.speed = 0Si on crée à nouveau deux instances de notre classe Car et qu’on imprime leur attribut speed, on voit que l’attribut existe et qu’il est bien à zéro, tel qu’on l’a initialisé :
class Car:
def __init__(self):
self.color = ""
self.brand = ""
self.speed = 0
blue_car = Car()
red_car = Car()
print(blue_car.speed)
print(red_car.speed)Si on lance se programme, on voit bien le résultat suivant :

Même si nous n’avons rien assigné explicitement après la création des objets, les attributs existent déjà grâce aux valeurs définies dans __init__.
Dans notre exemple, grâce à __init__, nous garantissons que toutes les voitures auront une couleur, une marque et une vitesse.
Pour l’instant, lorsque nous créons une voiture à partir de notre classe, sa marque et sa couleur sont initialisées à une chaîne de caractères vide. Étant donné qu’une voiture possède toujours une marque et une couleur qui lui sont propres, imaginons que nous souhaitions que l’utilisateur de notre classe renseigne ces deux attributs lors de la création d’un objet.
Pour cela, on peut ajouter les attributs qu’on souhaite recevoir lors de l’initialisation de notre objet, en paramètres additionnels de la méthode __init__ :
class Car:
def __init__(self, p_brand, p_color):
self.color = p_color
self.brand = p_brand
self.speed = 0
blue_car = Car()
red_car = Car()
print(blue_car.speed)
print(red_car.speed)Maintenant, si lors de la création de nos objets, on ne renseigne pas la marque et la couleur des voitures, on obtient l’exception suivante :

Adaptons donc notre code afin de passer les deux paramètres à notre fonction __init__. Pour cela, il suffit de passer les deux paramètres lors de la création de nos objets :
class Car:
def __init__(self, p_brand, p_color):
self.color = p_color
self.brand = p_brand
self.speed = 0
blue_car = Car("BMW", "blue")
red_car = Car("Peugeot", "red")
print(blue_car.brand, blue_car.color)
print(red_car.brand, red_car.color)Et maintenant, si on relance notre programme, on voit bien que les objets ont été créés, et que leurs attributs ont été initialisés avec les valeurs qu’on a passées en paramètre lors de leur création :

Paramètres optionnels
En plus de définir des paramètres d’initialisation obligatoires, on peut aussi définir des paramètres optionnels. Pour définir un paramètre optionnel, il suffit de lui assigner une valeur par défaut, dans la signature de la méthode __init__. Il est important de noter que les paramètres optionnels doivent obligatoirement être définis après tous les paramètres obligatoires.
Pour illustrer cela, ajoutons un paramètre optionnel p_speed à notre méthode __init__ :
class Car:
def __init__(self, p_brand, p_color, p_speed=0):
self.color = p_color
self.brand = p_brand
self.speed = p_speed
blue_car = Car("BMW", "blue", 20)
red_car = Car("Peugeot", "red")
print(blue_car.brand, blue_car.color, blue_car.speed)
print(red_car.brand, red_car.color, red_car.speed)Le paramètre p_speed étant optionnel, nous l’avons renseigné uniquement pour notre objet blue_car, ce qui nous donne le résultat suivant :

La voiture initialisée avec une vitesse de 20 a bien la valeur 20 en tant que vitesse, alors que celle pour laquelle nous n’avons pas passé de vitesse en paramètre, possède la vitesse par défaut, qui est de 0.
Méthodes de classe
Une classe ne sert pas uniquement à stocker des données. Elle peut également définir des méthodes, c’est-à-dire des fonctions associées à l’objet et qui servent à interagir avec l’objet en question. Une méthode doit être indentée à l’intérieur de la classe et prend toujours en tant que premier paramètre, le paramètre self, qui est une référence à l’objet en question, et puis nous pouvons ajouter autant de paramètres que nous le souhaitons, comme pour toute autre fonction.
class MyClass:
def my_method(self, p_param_1, p_param_2, ...):
# method codePour utiliser une méthode, il suffit ensuite de faire suivre une instance de notre classe par un point, suivi du nom de la méthode à appeler, à laquelle on passe tous les paramètres à l’exception du paramètre self, qui est automatiquement assigné avec une référence à l’objet lui-même :
class MyClass:
def my_method(self, p_param_1, p_param_2, ...):
my_obj = MyClass()
my_obj.my_method(param_1, param_2, ...)Dans notre cas, nous allons implémenter deux méthodes. La première va s’appeler accelerate et va prendre une vitesse en paramètre qui sera ajoutée à la vitesse actuelle de notre voiture. La deuxième méthode va s’appeler decelerate et va prendre une vitesse qu’on souhaite soustraire de la vitesse actuelle de la voiture :
class Car:
def __init__(self, p_brand, p_color, p_speed=0):
self.color = p_color
self.brand = p_brand
self.speed = p_speed
def accelerate(self, p_speed):
self.speed += p_speed
def decelerate(self, p_speed):
self.speed -= p_speed
if self.speed < 0:
self.speed = 0
blue_car = Car("BMW", "blue", 20)
red_car = Car("Peugeot", "red")
print(blue_car.brand, blue_car.color, blue_car.speed)
print(red_car.brand, red_car.color, red_car.speed)
blue_car.accelerate(50)
print(blue_car.brand, blue_car.color, blue_car.speed)
print(red_car.brand, red_car.color, red_car.speed)
blue_car.decelerate(10)
print(blue_car.brand, blue_car.color, blue_car.speed)
print(red_car.brand, red_car.color, red_car.speed)
blue_car.decelerate(100)
print(blue_car.brand, blue_car.color, blue_car.speed)
print(red_car.brand, red_car.color, red_car.speed)Maintenant, quand on lance notre programme, on observe la chose suivante :

Comme on peut le constater, la voiture bleu est tout d’abord initialisée à une vitesse de 20, puis on accélère de 50 et on se retrouve avec une vitesse de 70, puis on décélère une première fois à une vitesse de 60, pour finalement décélérer jusqu’à 0. Comme nous n’utilisons aucune méthode sur la voiture rouge, sa vitesse reste à 0 du début à la fin de l’exécution de notre programme.
Conclusion
Et voilà, nous avons posé les bases de la programmation orientée objet en Python. Nous avons vu ce qu’est une classe, ce qu’est un objet, comment définir des attributs, et comment ajouter des méthodes pour manipuler les données. Il y a énormément de sujets à traiter lorsque l’on parle de classes et de programmation orientée objet, mais nous allons nous arrêter là dans le cadre de ce cours d’introduction à Python.