Surcharge des opérateurs Python

Vous pouvez changer la signification d'un opérateur en Python en fonction des opérandes utilisés. Dans ce didacticiel, vous apprendrez à utiliser la surcharge d'opérateurs dans la programmation orientée objet Python.

Surcharge des opérateurs Python

Les opérateurs Python fonctionnent pour les classes intégrées. Mais le même opérateur se comporte différemment avec différents types. Par exemple, l' +opérateur effectuera une addition arithmétique sur deux nombres, fusionnera deux listes ou concaténera deux chaînes.

Cette fonctionnalité en Python qui permet au même opérateur d'avoir une signification différente selon le contexte est appelée surcharge d'opérateur.

Alors, que se passe-t-il lorsque nous les utilisons avec des objets d'une classe définie par l'utilisateur? Considérons la classe suivante, qui tente de simuler un point dans un système de coordonnées 2D.

 class Point: def __init__(self, x=0, y=0): self.x = x self.y = y p1 = Point(1, 2) p2 = Point(2, 3) print(p1+p2)

Production

 Traceback (dernier appel le plus récent): Fichier "", ligne 9, en version imprimée (p1 + p2) TypeError: type (s) d'opérande non pris en charge pour +: 'Point' et 'Point'

Ici, nous pouvons voir que a a TypeErrorété déclenché, car Python ne savait pas comment ajouter deux Pointobjets ensemble.

Cependant, nous pouvons réaliser cette tâche en Python grâce à la surcharge d'opérateurs. Mais d'abord, voyons les fonctions spéciales.

Fonctions spéciales Python

Les fonctions de classe commençant par un double trait de soulignement __sont appelées des fonctions spéciales en Python.

Ces fonctions ne sont pas les fonctions typiques que nous définissons pour une classe. La __init__()fonction que nous avons définie ci-dessus est l'une d'entre elles. Il est appelé chaque fois que nous créons un nouvel objet de cette classe.

Il existe de nombreuses autres fonctions spéciales en Python. Visitez les fonctions spéciales Python pour en savoir plus à leur sujet.

En utilisant des fonctions spéciales, nous pouvons rendre notre classe compatible avec les fonctions intégrées.

 >>> p1 = Point(2,3) >>> print(p1) 

Supposons que nous souhaitons que la print()fonction affiche les coordonnées de l' Pointobjet au lieu de ce que nous avons obtenu. Nous pouvons définir une __str__()méthode dans notre classe qui contrôle la façon dont l'objet est imprimé. Voyons comment nous pouvons y parvenir:

 class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x,self.y)

Maintenant, essayons à print()nouveau la fonction.

 class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0), (1))".format(self.x, self.y) p1 = Point(2, 3) print(p1)

Production

 (2, 3)

C'est mieux. Il s'avère que cette même méthode est invoquée lorsque nous utilisons la fonction intégrée str()ou format().

 >>> str(p1) '(2,3)' >>> format(p1) '(2,3)'

Ainsi, lorsque vous utilisez str(p1)ou format(p1), Python appelle la p1.__str__()méthode en interne . D'où le nom, fonctions spéciales.

Revenons maintenant à la surcharge des opérateurs.

Surcharge de l'opérateur +

Pour surcharger l' +opérateur, nous devrons implémenter la __add__()fonction dans la classe. Un grand pouvoir implique de grandes responsabilités. Nous pouvons faire ce que nous voulons, à l'intérieur de cette fonction. Mais il est plus judicieux de renvoyer un Pointobjet de la somme des coordonnées.

 class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x, self.y) def __add__(self, other): x = self.x + other.x y = self.y + other.y return Point(x, y)

Maintenant, essayons à nouveau l'opération d'addition:

 class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x, self.y) def __add__(self, other): x = self.x + other.x y = self.y + other.y return Point(x, y) p1 = Point(1, 2) p2 = Point(2, 3) print(p1+p2)

Production

 (3,5)

Ce qui se passe réellement, c'est que, lorsque vous utilisez p1 + p2, Python appelle p1.__add__(p2)ce qui est à son tour Point.__add__(p1,p2). Après cela, l'opération d'ajout est effectuée comme nous l'avons spécifié.

De même, nous pouvons également surcharger d'autres opérateurs. La fonction spéciale que nous devons implémenter est présentée ci-dessous.

Opérateur Expression Intérieurement
Une addition p1 + p2 p1.__add__(p2)
Soustraction p1 - p2 p1.__sub__(p2)
Multiplication p1 * p2 p1.__mul__(p2)
Puissance p1 ** p2 p1.__pow__(p2)
Division p1 / p2 p1.__truediv__(p2)
Division étage p1 // p2 p1.__floordiv__(p2)
Reste (modulo) p1 % p2 p1.__mod__(p2)
Décalage gauche au niveau du bit p1 << p2 p1.__lshift__(p2)
Décalage vers la droite au niveau du bit p1>> p2 p1.__rshift__(p2)
ET au niveau du bit p1 & p2 p1.__and__(p2)
OU au niveau du bit p1 | p2 p1.__or__(p2)
XOR au niveau du bit p1 p2 p1.__xor__(p2)
Pas au niveau du bit ~p1 p1.__invert__()

Surcharger les opérateurs de comparaison

Python ne limite pas la surcharge d'opérateurs aux seuls opérateurs arithmétiques. Nous pouvons également surcharger les opérateurs de comparaison.

Supposons que nous voulions implémenter le symbole moins que <dans notre Pointclasse.

Comparons la grandeur de ces points à partir de l'origine et retournons le résultat à cet effet. Il peut être mis en œuvre comme suit.

 # overloading the less than operator class Point: def __init__(self, x=0, y=0): self.x = x self.y = y def __str__(self): return "((0),(1))".format(self.x, self.y) def __lt__(self, other): self_mag = (self.x ** 2) + (self.y ** 2) other_mag = (other.x ** 2) + (other.y ** 2) return self_mag < other_mag p1 = Point(1,1) p2 = Point(-2,-3) p3 = Point(1,-1) # use less than print(p1 

Output

 True False False

Similarly, the special functions that we need to implement, to overload other comparison operators are tabulated below.

Operator Expression Internally
Less than p1 < p2 p1.__lt__(p2)
Less than or equal to p1 <= p2 p1.__le__(p2)
Equal to p1 == p2 p1.__eq__(p2)
Not equal to p1 != p2 p1.__ne__(p2)
Greater than p1> p2 p1.__gt__(p2)
Greater than or equal to p1>= p2 p1.__ge__(p2)

Articles intéressants...