Les classes en Python
Les classes sont des structures de données qui permettent de regrouper des données et des fonctions qui agissent sur ces données. Un objet est une instance d'une classe. Le concept de programmation orientée objet remonte aux années 1960 , mais il a été popularisé par des langages comme C++, Java et Python.
Distinction entre classe et objet
Une classe est un modèle pour créer des objets. Elle définit les attributs et les méthodes que les objets de la classe auront. Un objet est une instance d'une classe et il est créé à l'aide du constructeur de la classe. Autrement dit, la classe est le plan pour construire des objets. Avec un même plan, vous pouvez construire plusieurs objets.
Définir une classe
En Python, une classe est définie à l'aide du mot-clé class
. Voici un exemple
de classe qui définit un point dans un espace à deux dimensions :
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def distance(self, other):
return ((self.x - other.x) ** 2 + (self.y - other.y) ** 2) ** 0.5
Dans cet exemple, la classe Point
a deux attributs x
et y
qui représentent
les coordonnées du point. La méthode __init__
est un constructeur qui initialise
les attributs de la classe. La méthode distance
calcule la distance entre le
point courant et un autre point passé en argument.
Pour créer une instance de la classe Point
, vous pouvez utiliser le constructeur
comme suit :
p1 = Point(0, 0)
p2 = Point(3, 4)
print(p1.distance(p2)) # 5.0
Constructeurs
Le constructeur d'une classe est une méthode spéciale appelée __init__
. Cette
méthode est appelée lors de la création d'une instance de la classe. Elle est
utilisée pour initialiser les attributs de la classe. Le premier argument de
la méthode __init__
est self
, qui est une référence à l'instance de la classe
qui est en cours de création. Les autres arguments sont les valeurs que vous
souhaitez utiliser pour initialiser les attributs de la classe.
Il n'est pas nécessaire de déclarer explicitement le constructeur dans une classe Python. Si vous ne le faites pas, Python crée un constructeur par défaut qui ne fait rien.
Contrairement à d'autres langages de programmation, Python ne permet pas de définir plusieurs constructeurs pour une classe. Cependant, vous pouvez définir des valeurs par défaut pour les arguments du constructeur pour simuler des constructeurs surchargés. Par exemples :
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
Dans cet exemple, si vous ne fournissez pas d'arguments lors de la création d'une
instance de la classe Point
, les valeurs par défaut 0
seront utilisées pour
les attributs x
et y
.
Attributs et méthodes
On appelle attributs les variables qui appartiennent à un objet. Les attributs
sont accessibles à l'aide de la notation pointée (.
). Par exemple, pour accéder
à l'attribut x
d'une instance de la classe Point
, vous pouvez utiliser p.x
.
Les méthodes sont des fonctions qui appartiennent à un objet. Elles sont définies
de la même manière que les fonctions, mais elles prennent toujours self
comme
premier argument. self
est une référence à l'instance de la classe elle-même, c'est-à-dire
l'objet sur lequel la méthode est appelée.
Par exemple, pour appeler la méthode distance
de la classe Point
, vous pouvez
utiliser p1.distance(p2)
. Notez que vous n'avez pas besoin de passer self
en
argument, Python le fait automatiquement pour vous.
En python, tous les attributs et méthodes d'une classe sont publics.
Cela signifie qu'ils peuvent être accédés et modifiés de l'extérieur de la classe.
Toutefois, la convention veut que les attributs et méthodes qui commencent par un
underscore _
soient considérés comme privés et ne doivent pas être accédés de
l'extérieur de la classe. Par exemple, vous pouvez définir un attribut privé comme
suit :
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
self._est_un_carre = x == y
Ceci n'est qu'une convention et vous pouvez toujours accéder aux attributs et méthodes privés en Python. Cependant, il est recommandé de ne pas le faire, car cela peut rendre votre code fragile et difficile à maintenir.
Attributes de classe et attributs d'instance
En Python, il existe deux types d'attributs : les attributs de classe et les attributs d'instance. Les attributs de classe sont partagés par toutes les instances de la classe, tandis que les attributs d'instance sont propres à chaque instance.
Les attributs de classe sont définis à l'extérieur des méthodes de la classe. Ils
sont accessibles à l'aide de la notation pointée (.
) à partir de la classe ou
de ses instances. Par exemple, pour définir un attribut de classe compteur
qui
compte le nombre d'instances de la classe Point
, vous pouvez faire :
class Point:
compteur = 0
def __init__(self, x, y):
self.x = x
self.y = y
Point.compteur += 1
Dans cet exemple, chaque fois qu'une nouvelle instance de la classe Point
est
créée, l'attribut de classe compteur
est incrémenté de 1
. Notez que le mot-clé
Point
est utilisé pour accéder à l'attribut de classe compteur
à l'intérieur
de la méthode __init__
. Aussi, compteur
n'est pas déclaré avec self
, ce qui
signifie qu'il s'agit d'un attribut de classe.
Les attributs d'instance sont définis à l'intérieur des méthodes de la classe.
Ils sont accessibles à l'aide de la notation pointée (.
) à partir de
l'instance de la classe représentée par self
. Par exemple, pour définir un
attribut d'instance couleur
qui représente la couleur d'un point, vous pouvez
faire :
class Point:
def __init__(self, x, y, couleur):
self.x = x
self.y = y
self.couleur = couleur
Méthodes de classe et méthodes statiques
Tout comme les attributs, les méthodes peuvent être de classe, statiques ou d'instance.
Les méthodes d'instance sont les plus courantes et sont définies à l'intérieur
de la classe avec self
comme premier argument. Elles agissent sur les données
de l'instance de la classe comme dans les exemples précédents.
Méthodes statiques
Les méthodes statiques sont définies avec le décorateur @staticmethod
.
Elles n'ont pas accès à l'instance de la classe (self
) et ne peuvent pas
modifier les attributs de l'instance. Elles sont utilisées pour des fonctions
qui n'ont pas besoin d'accéder aux données de l'instance, mais qui sont
liées à la classe. Voici un exemple de méthode statique :
class Conversion:
@staticmethod
def celsius_to_fahrenheit(celsius):
return (celsius * 9/5) + 32
Souvent, les méthodes statiques auraient pu être des fonctions indépendantes, mais elles sont définies à l'intérieur de la classe pour montrer qu'elles sont liées à la classe ou pour regrouper des fonctions similaires.
Dans certains langages de programmation, tout doit être un objet. Les méthodes statiques sont alors les seules façons de définir des fonctions. Java, particulièrement avant Java 8 et les fonctions lambda, est un exemple de langage où les méthodes statiques sont courantes.
Méthodes de classe
En Python, les classes sont également des objets. Il y a donc l'objet Point
qui est une instance de la classe type
. Ensuite il y a des objets p1
qui
sont des instances de la classe Point
. Les méthodes de classe sont définies
avec le décorateur @classmethod
. Elles prennent l'objet de la classe elle-même comme
premier argument, généralement nommé cls
. Elles sont utilisées pour des
fonctions qui agissent sur la classe plutôt que sur une instance spécifique.
Voici un exemple de méthode de classe qui fournit un constructeur alternatif
pour créer une instance de la classe Point
à partir d'un dictionnaire :
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
@classmethod
from_dict(cls, data: dict):
return cls(data['x'], data['y'])
d = {'x': 1, 'y': 2}
p = Point.from_dict(d)
Remarquez que dans cet exemple, lorsque nous appelons la méthode de classe
from_dict
, il n'y a pas besoin de fournir l'argument cls
. Python le
passe automatiquement comme pour les méthodes d'instance.
Un autre usage courant des méthodes de classe est la manipulation des attributs de classe. Par exemple, vous pouvez définir une méthode de classe qui incrémente un compteur d'instances de la classe :
class Compteur:
compte = 0
@classmethod
def increment(cls):
cls.compte += 1
Compteur.increment()
print(Compteur.compte) # Affiche 1
Méthodes spéciales
En Python, les méthodes spéciales sont des méthodes qui ont un nom spécial et
qui sont appelées automatiquement dans des situations particulières. Par exemple,
la méthode __init__
est appelée lors de la création d'une instance de la classe.
Voici quelques-unes des méthodes spéciales les plus couramment utilisées :
__init__(self, ...)
: Constructeur de la classe.__str__(self)
: Méthode appelée par la fonctionstr
pour obtenir une représentation sous forme de chaîne de caractères de l'objet.__repr__(self)
: Méthode appelée par la fonctionrepr
pour obtenir une représentation sous forme de chaîne de caractères de l'objet. La différence avec__str__
est que__repr__
doit retourner une chaîne de caractères qui peut être évaluée pour recréer l'objet.__eq__(self, other)
: Méthode appelée lors de l'évaluation de l'égalité entre deux objets à l'aide de l'opérateur==
.__lt__(self, other)
: Méthode appelée lors de l'évaluation de l'opérateur<
.__gt__(self, other)
: Méthode appelée lors de l'évaluation de l'opérateur>
.__le__(self, other)
: Méthode appelée lors de l'évaluation de l'opérateur<=
.__ge__(self, other)
: Méthode appelée lors de l'évaluation de l'opérateur>=
.__add__(self, other)
: Méthode appelée lors de l'addition de deux objets à l'aide de l'opérateur+
.__sub__(self, other)
: Méthode appelée lors de la soustraction de deux objets à l'aide de l'opérateur-
.__mul__(self, other)
: Méthode appelée lors de la multiplication de deux objets à l'aide__truediv__(self, other)
: Méthode appelée lors de la division de deux objets à l'aide de l'opérateur/
.
Voici un exemple de classe Point
qui redéfinit les méthodes __str__
et __eq__
:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"({self.x}, {self.y})"
def __eq__(self, other):
return self.x == other.x and self.y == other.y
Dans tous les cas, les méthodes commençant et se terminant par deux traits de
soulignement __
sont des méthodes spéciales et ne doivent pas être
appelées directement par le programmeur.