====== Méthodes magiques ======
===== Qu'est-ce =====
Supposons que l'on crée un objet ''A'' et que l'on crée des instances ''x'' et ''y'' de cet objet. On voudrait pouvoir les additionner.
>>> x = A()
>>> y = A()
>>> x + y
TypeError: unsupported operand type(s) for +: 'A' and 'A'
Le message d'erreur signal que l'opérateur ''+'' ne prend pas en charge notre classe ''A''.
Il est possible de doter notre classe des caractéristiques nécessaires pour rendre cette addition possible. Et cela est valable pour d'autres opérations : ''%%-, /, %, *%%'' et aussi des opérateurs de comparaison : ''%%<, <=, >, >=, ==, !=%%'' et beaucoup d'autres choses encore !
Il faut pour cela utiliser les **méthodes magiques** qui en Python sont toujours nommées avec des ''%%__%%''.
===== Liste =====
En voici une liste partielle. Vous pouvez aller voir la [[https://www.tutorialsteacher.com/python/magic-methods-in-python|liste complète]].
== new ==
''%%__new__(cls)%%''. C'est une méthode de classe. Elle définit ce qui se passe on instancie un objet de la classe. La méthode par défaut se contente d'appeler ''%%__init__%%''
== str ==
''%%__str__(self)%%''. Appelée quand on demande une conversion de l'objet en chaîne de caractères. C'est le cas quand on appelle la fonction ''print''.
== repr ==
''%%__repr__(self)%%''. Ressemble à la précédente mais est utilisée lors de l'affichage en console.
== add ==
''%%__add__(A, B)%%''. Quant on ajoute ''A + B'', alors on appelle la méthode pour ''A''.
== sub, mul, div ==
Même chose pour :
* la soustraction ''%%__sub__(A, B)%%'',
* multiplication ''%%__mul__(A, B)%%'',
* la division ''%%__div__(A, B)__%%'',
* la division entière (''%%//%%'') ''%%__floordiv__(A, B)%%'',
* le modulo ''%%__mod__(A, B)__%%'',
* la puissance (''%%**%%'') ''%%__pow__(A, B)%%''.
== incrément et autre ==
On aime utilisé des opérateurs comme ''%%+=%%''. Si on demande ''A += B'', il faudra définir ''%%__iadd__(A, B)%%''.
Même chose avec ''%%__isub__%%'', ''%%__imul__%%'', ''%%__idiv__%%'' et ''%%__ifloordiv__%%''.
== transtypages ==
De même que l'on peut convertir en ''str'' avec ''%%__str__%%'' on peut prendre en charge le transtypage en ''int'', ''float'' et ''complex'' avec ''%%__int__%%'', ''%%__float__%%'' et ''%%__complex__%%''.
== valeur absolue ==
''%%__abs__(self)%%''
== Comparaison ==
* ''%%A >= B%%'' -- //greater or equal// -- ''%%__ge__(A, B)%%''
* ''%%A <= B%%'' -- //lower or equal// -- ''%%__le__(A, B)%%''
* ''%%A > B%%'' -- //greater than// -- ''%%__gt__(A, B)%%''
* ''%%A < B%%'' -- //lower than// -- ''%%__lt__(A, B)%%''
* ''%%A == B%%'' -- //equal// -- ''%%__eq__(A, B)%%''
* ''%%A != B%%'' -- //not equal// -- ''%%__ne__(A, B)%%''
===== Exemple =====
Pour illustrer, donnons l'exemple de vecteurs 2D que l'on veut pouvoir ajouter et dont on veut pouvoir trouver la norme en utilisant ''abs''.
from math import sqrt
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(A, B):
x = self.x + B.x
y = self.y + B.y
return Vector(x, y)
def __sub__(A, B):
x = self.x - B.x
y = self.y - B.y
return Vector(x, y)
def __abs__(self):
return sqrt(self.x**2 + self.y**2)
def __str__(self):
return "({} ; {})".format(self.x, self.y)
if __name__ == "__main__":
# exemple d'utilisation
a = Vector(3, 4)
b = Vector(5, -2)
c = a + b
print(c) # affiche "(8 ; 2)"
d = a - b
print(d) # affiche "(-2 ; 6)"
l = abs(a)
print(l) # affiche 5.0