Les méthodes spéciales pour renforcer vos classes Python

Les méthodes spéciales intégrées à Python sont utilisées pour améliorer les fonctionnalités de vos classes. On les identifie par un double trait de soulignement au début et à la fin.

méthodes spéciales

La méthode spéciale que vous connaissez déjà est sans doute la méthode __init__(). Elle est responsable de la construction des objets et est toujours appelée lors de l’instanciation d’un objet.

En fait, Python permet de surcharger les opérateurs, ce qui permet d’étendre les fonctionnalités de votre code.

En tant que programmeurs Python, vous n’êtes pas censés appeler directement les méthodes spéciales. Au lieu de cela, vous êtes censés utiliser les opérations de haut niveau (comme les opérateurs + et ==) qui reposent sur ces méthodes spéciales.

Les classes peuvent surcharger la plupart des opérations de type intégrées. Cela inclut les expressions, mais aussi les opérations de base comme l’affichage et la création d’objets.

Les classes peuvent intercepter les opérateurs Python

Le langage Python définit un mappage de certaines opérations vers une méthode spéciale dans une classe. Par conséquent, il est possible de surcharger les opérateurs en fournissant des méthodes spéciales pour intercepter les opérations.

En fait, ces méthodes sont appelées automatiquement lorsque des instances apparaissent dans des opérations intégrées. Par exemple, si une instance hérite une méthode __add__(), cette méthode est appelée chaque fois que l’objet apparaît dans une expression +.

Par exemple, lorsque vous essayez d’additionner deux instances d’une classe à l’aide de l’opérateur +, l’interpréteur Python entre dans la définition de votre classe et recherche une implémentation de la méthode spéciale __add__(). S’il la trouve, il exécute son code, comme n’importe quelle autre méthode ou fonction.

x = 20
>>> x + 5
25

OU :

>>> x.__add__(5)
25

En réalité, l’opération x+5, implique que l’opérateur + appelle la méthode __add__(5).

Dans la plupart des cas, il n’y a pas de valeurs par défaut pour la surcharge des méthodes d’opérateurs et aucune n’est requise. Si une classe ne définit ni n’hérite d’une méthode d’opérateur surchargé, l’opération correspondante ne sera pas prise en charge pour les instances de la classe. S’il n’y a pas de __add__(), par exemple, les expressions + déclencheront des exceptions.

Prenant un autre exemple :

nums = [1, 2, 3, 4, 5]
print(len(nums)) #5
print(nums.__len__()) #5

Donc, len(nums) est la meme chose que nums.__len__().

Chaque fois que nous utilisons une fonction intégrée, elle essaie de trouver une méthode spéciale qui effectue la tâche, comme la fonction len() qui trouve la méthode magique __len__ méthode dans cet objet.

Afin de surcharger un opérateur dans une classe personnalisée, la méthode spéciale correspondante doit être surchargée.

Donc, les opérateurs permettent aux classes de s’intégrer au modèle d’objet de Python. En surchargeant les opérations, les objets définis par l’utilisateur que nous implémentons avec des classes, peuvent agir comme des éléments intégrés, et fournir une cohérence ainsi qu’une compatibilité avec les interfaces.

Les méthodes spéciales en action

Pour expliquer ce concept, considérons une classe qui va compter les valeurs qui lui sont ajoutées. Le code devrait nous permettre de faire plusieurs choses.
Premièrement, il doit garder une trace des valeurs qui lui sont ajoutées dans une liste. Deuxièmement, nous allons surcharger la méthode len() pour renvoyer le nombre d’éléments ajoutés à la liste.
Enfin, la méthode str() doit être surchargée afin que l’affichage d’une instance de classe retourne des informations sur les valeurs qui lui ont été ajoutées.

Initialisons la classe en utilisant la méthode __init__. Puis, nous allons créer une liste vide pour garder une trace des valeurs ajoutées à l’objet.

class Compteur:
    def __init__(self):
        self.valeurs = []

Maintenant, surchargeons la méthode len(), donc au lieu d’avoir une erreur, l’objet retournera la longueur de la liste contenant les valeurs. La méthode len() n’est pas défini dans notre classe.

compteur = Compteur()
len(compteur)

TypeError: object of type 'Compteur' has no len()

Pour résoudre ce problème, nous allons ajouter une méthode spéciale __len__ à notre classe.

def __len__(self):
    return len(self.valeurs)

Ensuite, nous allons surcharger la méthode str(), afin que nous puissions retourner des informations sur l’objet. Donc, notre code va retourner la liste des valeurs, le nombre de valeurs dans la liste et la somme des valeurs. Notez que pour obtenir le nombre d’éléments dans la liste, nous utilisons la méthode précédemment surchargée len().

def __str__(self):
    som_compteur = sum(self.valeurs)
    return f"Les valeurs: {self.valeurs}\nLe nombre des valeurs: {len(self)}\nTotal: {som_compteur}"
compteur = Compteur()
print(compteur)

Si nous créons une instance de la classe Compteur et l’affichons, nous obtiendrons ce qui suit :

Les valeurs: []
Le nombre des valeurs: 0
Total: 0

Maintenant que nous avons initialisé l’instance, ajoutons des méthodes pour permettre aux valeurs d’être ajoutées et soustraites au total. Ici, nous utiliserons les méthodes iadd et isub . Le préfixe i signifie in-place (en place), ce qui signifie qu’il surcharge les opérateurs += et -=. Vous pouvez également surcharger les méthodes standards add et sub.

Créer une classe personnalisée

Nous allons ajouter des valeurs positives et négatives à la liste de valeurs, dans la méthode isub. Nous multiplierons la valeur par -1 pour la stocker comme négative dans la liste.

Voici le code complet :

class Compteur:
    def __init__(self):
        self.valeurs = []

    def __len__(self):
        return len(self.valeurs)

    def __iadd__(self, other):
        self.valeurs.append(other)
        return self

    def __isub__(self, other):
        self.valeurs.append(-1 * other)
        return self

    def __str__(self):
        som_compteur = sum(self.valeurs)
        return f"Les valeurs: {self.valeurs}\nNombre des valeurs: {len(self)}\nTotal: {som_compteur}"

Maintenant, voyons le code en action. Tout d’abord, nous allons créer un objet compteur et y ajouter des valeurs positives et négatives.

compteur = Compteur()

compteur += 2
compteur += 3
compteur += 5
compteur -= 4

print(compteur)
Les valeurs: [2, 3, 5, -4]
Nombre des valeurs: 4
Total: 6

Enlevez la méthode __str__(), puis exécutez le code pour voir ce qui se passera.

Ce concept magnifique est connue sous le nom de modèle de données Python et permet aux développeurs d’élargir les fonctionnalités du langage telles que les séquences, l’itération, la surcharge d’opérateurs, l’accès aux attributs, etc.

Conclusion

La surcharge des opérateurs est une fonctionnalité facultative. En réalité, elle est principalement utilisée par les personnes qui développent des outils pour d’autres programmeurs Python, et non par les développeurs d’applications.

Et, franchement, vous ne devriez probablement pas l’utiliser simplement parce qu’elle semble efficace et magnifique. À moins qu’une classe n’ait besoin d’imiter les interfaces de type intégrées, vous devrait généralement utiliser des méthodes plus simples. Pourquoi une application de base de données d’employés prendrait-elle en charge des expressions telles que * et +, par exemple ?

Les méthodes spéciales pour renforcer vos classes Python

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Retour en haut