Surcharge des opérateurs en Python

Surcharge des opérateurs en Python

La surcharge d’opérateurs vous permet de redéfinir la signification d’opérateur en fonction de votre classe. C’est la magie de la surcharge d’opérateurs que nous avons pu utiliser l’opérateur + pour ajouter deux objets numériques, ainsi que pour concaténer deux objets chaîne.

Cette fonctionnalité en Python, qui permet à un même opérateur d’avoir une signification différente en fonction du 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 :

Exemple 1 :
                                class Point:
                                    def __init__(self, x, y):
                                        self.x = x
                                        self.y = y
                                
                                
                                p1 = Point(2, 4)
                                p2 = Point(5, 1)
                                
                                p3 = p1+p2
                            
Traceback (most recent call last):
File "prog.py", line 10, in < module>
p3 = p1+p2
TypeError: unsupported operand type(s) for +: 'Point' and 'Point'

TypeError a été généré car Python ne savait pas comment ajouter deux objets Point ensemble.
Cependant, la bonne nouvelle est que nous pouvons apprendre cela à Python en surchargeant les opérateurs. Mais tout d’abord, parlons des fonctions spéciales.

La surcharge de l'opérateur est obtenue en définissant une méthode spéciale dans la définition de classe. Les noms de ces méthodes commencent et finissent par un double soulignement (__).

Opérateurs arithmétiques

Opérateur +

Pour surcharger l'opérateur +, nous devrons implémenter la fonction __add __ () dans la classe. Un grand pouvoir implique de grandes responsabilités. Nous pouvons faire ce que nous voulons, dans cette fonction.

Exemple 2 :
                                class Point:
                                    def __init__(self, x, y):
                                        self.x = x
                                        self.y = y
                                    
                                    def __str__(self):
                                        return "({0},{1})".format(self.x, self.y)
                                
                                    def __add__(self, p):
                                        a = self.x + p.x
                                        b = self.y + p.y
                                        return Point(a, b)
                                
                                
                                p1 = Point(2, 4)
                                p2 = Point(5, 1)
                                
                                p3 = p1+p2
                                print(p3)
                            
(7,5)

Si l'expression est de la forme x + y, Python l'interprète comme x .__ add __ (y). La version de la méthode __add __ () appelée dépend du type de x et de y.

Fonctions spéciales de surcharge de l'opérateur en Python

Le tableau suivant répertorie les opérateurs et leur méthode spéciale correspondante.

OperateurExpressionInterprétation Python
Additionp1 + p2p1.__add__(p2)
Soustrationp1 - p2p1.__sub__(p2)
Multiplicationp1 * p2p1.__mul__(p2)
Puissancep1 ** p2p1.__pow__(p2)
Divisionp1 / p2p1.__truediv__(p2)
Division entièrep1 // p2p1.__floordiv__(p2)
le reste (modulo)p1 % p2p1.__mod__(p2)
Décalage binaire gauchep1 << p2p1.__lshift__(p2)
Décalage binaire droitep1 >> p2p1.__rshift__(p2)
ET binairep1 & p2p1.__and__(p2)
OU binairep1 | p2p1.__or__(p2)
XORp1 ^ p2p1.__xor__(p2)
NON binaire~p1p1.__invert__()

Surcharge des opérateurs de comparaison

Python ne limite pas la surcharge des 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 inférieur à < dans notre classe Point.
Comparons la magnitude de ces points depuis l'origine et retournons le résultat. Il peut être implémenté comme suit.

Exemple 3 :
                                import math
                                class Point:
                                    def __init__(self, x, y):
                                        self.x = x
                                        self.y = y
                                    
                                    def __lt__(self, p):
                                        m_self = math.sqrt((self.x ** 2) + (self.y ** 2))
                                        m2_p = math.sqrt((p.x ** 2) + (p.y ** 2))
                                        return m_self < m2_p
                                
                                
                                p1 = Point(2, 4)
                                p2 = Point(5, 1)
                                
                                if p1 < p2:
                                    print("p2 est plus loin que p1")
                            
p2 est plus loin que p1

De même, les fonctions spéciales que nous devons implémenter pour surcharger d’autres opérateurs de comparaison sont résumées ci-dessous.

OperateurExpressionInterprétation Python
Inférieur àp1 < p2p1.__lt__(p2)
Inférieur ou égalp1 <= p2p1.__le__(p2)

Egal

p1 == p2p1.__eq__(p2)
différentp1 != p2p1.__ne__(p2)
Supérieur àp1 > p2p1.__gt__(p2)
Supérieur ou égalp1 >= p2p1.__ge__(p2)
Exemple 4 :
                                    import math

                                    class Point:
                                        def __init__(self, x=0, y=0):
                                            self.__x = x
                                            self.__y = y
                                    
                                        # Opérateur +
                                        def __add__(self, p):
                                            return Point(self.__x + p.__x, self.__y + p.__y)
                                    
                                        # Opérateur -
                                        def __sub__(self, p):
                                            return Point(self.__x - p.__x, self.__y - p.__y)
                                    
                                        # Opérateur <
                                        def __lt__(self, p):
                                            m_self = math.sqrt((self.__x ** 2) + (self.__y ** 2))
                                            m_p = math.sqrt((p.__x ** 2) + (p.__y ** 2))
                                            return m_self < m_p
                                    
                                        # Opérateur <=
                                        def __le__(self, p):
                                            m_self = math.sqrt((self.__x ** 2) + (self.__y ** 2))
                                            m_p = math.sqrt((p.__x ** 2) + (p.__y ** 2))
                                            return m_self <= m_p
                                    
                                        # Opérateur >
                                        def __gt__(self, p):
                                            m_self = math.sqrt((self.__x ** 2) + (self.__y ** 2))
                                            m_p = math.sqrt((p.__x ** 2) + (p.__y ** 2))
                                            return m_self > m_p
                                    
                                        # Opérateur >=
                                        def __ge__(self, p):
                                            m_self = math.sqrt((self.__x ** 2) + (self.__y ** 2))
                                            m_p = math.sqrt((p.__x ** 2) + (p.__y ** 2))
                                            return m_self >= m_p
                                    
                                        # Opérateur ==
                                        def __eq__(self, p):
                                            m_self = math.sqrt((self.__x ** 2) + (self.__y ** 2))
                                            m_p = math.sqrt((p.__x ** 2) + (p.__y ** 2))
                                            return m_self == m_p
                            

Rédigé par M. ESSADDOUKI

Many people realize their hearts desires late in life. Continue learning, never stop striving and keep your curiosity sharp, and you will never become too old to appreciate life.