Surcharge d'opérateurs

11.4 Surcharge d'opérateurs

Objectifs d'apprentissage

À la fin de cette section, vous devriez être capable de :

  • Identifier les méthodes magiques et décrire leur utilité.
  • Développer des opérateurs arithmétiques et de comparaison surchargés pour des classes définies par l'utilisateur.

Méthodes magiques et personnalisation

Les méthodes magiques (magic methods) sont des méthodes spéciales qui effectuent des actions pour les utilisateurs, généralement hors de leur vue. Les méthodes magiques sont également appelées méthodes « dunder », car elles doivent commencer et se terminer par un double trait de soulignement (__). Ex. : __init__() est une méthode magique utilisée conjointement avec __new__() pour créer une nouvelle instance et initialiser des attributs avec une simple ligne comme eng = Engineer(). Un programmeur peut définir explicitement une méthode magique dans une classe définie par l'utilisateur pour personnaliser le comportement de la méthode.

Faites le point

Personnalisation de __str__() dans une classe définie par l'utilisateur, Engineer

Concepts en pratique

Méthodes magiques

1.
Laquelle des propositions suivantes est une méthode magique ?
  1. add()
  2. _add_()
  3. __add__()
2.
Pourquoi les méthodes magiques sont-elles spéciales ?
  1. ne peuvent pas être appelées par l'utilisateur
  2. effectuent des actions internes
  3. ont des définitions fixes
3.
Considérez l'exemple ci-dessus et identifiez la ou les méthode(s) magique(s) dans le programme mis à jour.
  1. __init__()
  2. __str__()
  3. __init__(), __str__()

Surcharge des opérateurs arithmétiques

La surcharge d'opérateurs (operator overloading) fait référence à la personnalisation du fonctionnement d'un opérateur intégré. Les opérateurs arithmétiques sont couramment surchargés pour permettre de modifier facilement les instances de classes définies par l'utilisateur.

Faites le point

Surcharge de __add__() pour une classe définie par l'utilisateur, Account

Opérateur arithmétique (Opération) Méthode magique
+ (Addition)
__add__(self, other)
- (Soustraction)
__sub__(self, other)
* (Multiplication)
__mul__(self, other)
/ (Division)
__truediv__(self, other)
% (Modulo)
__mod__(self, other)
** (Puissance)
__pow__(self, other)
Tableau 11.1 Opérateurs arithmétiques et méthodes magiques.

Concepts en pratique

Surcharge des opérateurs arithmétiques

4.
Un programmeur qui définit explicitement l'opérateur modulo pour sa classe définie par l'utilisateur est en train de ___________ l'opérateur.
  1. surcharger
  2. réécrire
  3. implémenter
5.
Étant donné le code ci-dessous, quel argument correspond au paramètre other dans l'appel à Account.__add__() ?
acct_a = Account("Ashe", 6492)
acct_b = Account("Bevins", 5210)

acct_ab = acct_a + acct_b
  1. acct_a
  2. acct_b
  3. acct_ab
6.
Quelle définition de __sub__() surcharge l'opérateur - pour que le code ci-dessous fonctionne ?
class Pair:
  def __init__(self, x=0, y=0):
    self.x = x
    self.y = y
  # Define __sub__()

p1 = Pair(10, 2)
p2 = Pair(8, 4)
p3 = p1 - p2
print(p3.x, p3.y)
  1.   def __sub__(self):
        return Pair(self.x - other.x, self.y - other.y)
    
  2.   def __sub__(self, other):
        return self.x - other.x, self.y - other.y
    
  3.   def __sub__(self, other):
        return Pair(self.x - other.x, self.y - other.y)
    

Surcharge des opérateurs de comparaison

Les opérateurs de comparaison peuvent également être surchargés, tout comme les opérateurs arithmétiques.

Opérateur de comparaison (Opération) Méthode magique
< (Inférieur à)
__lt__(self, other)
> (Supérieur à)
__gt__(self, other)
<= (Inférieur ou égal à)
__le__(self, other)
>= (Supérieur ou égal à)
__ge__(self, other)
== (Égal à)
__eq__(self, other)
!= (Différent de)
__ne__(self, other)
Tableau 11.2 Opérateurs de comparaison et méthodes magiques.

Exemple 11.2

Surcharge des opérateurs de comparaison pour la classe Account

Code Sortie
class Account:
  def __init__(self, name="", amount=0):
    self.name = name
    self.amount = amount

  def __str__(self):
    return f"{self.name}: ${self.amount}"

  def __lt__(self, other):
    return self.amount < other.amount

  def __gt__(self, other):
    return self.amount > other.amount

  def __eq__(self, other):
    return self.amount == other.amount

acct_a = Account("Ashe", 6492)
acct_b = Account("Bevins", 5210)

print(acct_a < acct_b)
print(acct_a > acct_b)
acct_a.amount = 5210
print(acct_a == acct_b)
False

True

True
Tableau 11.3

Concepts en pratique

Surcharge des opérateurs de comparaison

Considérez l'exemple ci-dessus.

7.
Combien d'opérateurs sont surchargés ?
  1. 3
  2. 4
  3. 5
8.
Quel code surcharge de manière appropriée l'opérateur <= ?
  1.   def __le__(other):
        return self.amount <= other.amount
    
  2.   def __le__(self, other):
        return self.amount <= other.amount
    
  3.   def __le__(self, other):
        return other.amount <= self.amount
    
9.
Quel type de valeur __gt__() renvoie-t-il ?
  1. instance d'Account
  2. booléen
  3. entier

À vous d'essayer

Combinaison de journaux d'exercices

La classe ExerciseLog possède deux attributs d'instance : e_type, le type d'exercice, et duration, le temps consacré à l'exercice.

Surchargez l'opérateur + pour combiner deux objets ExerciseLogs de telle sorte que :

  • Si les types d'exercices sont différents, combinez-les avec " and " entre les deux. Sinon, utilisez le même type sans le dupliquer.
  • Additionnez les durées ensemble.

Pour l'entrée suivante :

    walk
    5
    run
    30

La sortie est :

    walk and run: 35 minutes

À vous d'essayer

Extension de la classe Account

L'utilisation de isinstance() permet au programmeur de définir différents comportements en fonction du type d'un objet. Le premier paramètre est l'objet et le second paramètre est le type ou la classe. Ex. : isinstance(my_var, int) renvoie True si my_var est un entier.

Étendez l'exemple existant de la classe Account afin que l'opérateur d'addition puisse également être utilisé pour ajouter une valeur entière à l'attribut amount d'un objet Account'.