Qu'est-ce que NotImplemented ?
Tout comme None, NotImplemented est un singleton : il n'existe qu'une seule instance.
Il est utilisé dans les méthodes spéciales des opérateurs comme __add__ ou __eq__. Il veut dire : « Je ne sais pas faire cette opération avec cet objet ».
class Panier: def __init__(self, articles): self.articles = articles def __add__(self, autre): if not isinstance(autre, Panier): return NotImplemented return Panier(self.articles + autre.articles)
Dans ce cas, un Panier ne sait pas s'additionner avec un objet d'une autre classe. Mais NotImplemented ne s'arrête pas là. Pour compléter la phrase précédente : « Je ne sais pas faire cette opération avec cet objet, alors je lui passe la main pour que lui-même essaye de faire l'opération ».
Quelle différence entre NotImplemented et NotImplementedError ?
Bien que les noms se ressemblent, ils n'ont rien à voir. NotImplementedError est une exception que l'on lève généralement dans deux situations :
-
dans une méthode qu'une classe fille est censée réécrire... avant l'arrivée du module abc
-
dans une classe en cours d'écriture pour signaler qu'une méthode n'est pas encore implémentée
class Livraison: def calculer_frais(self): raise NotImplementedError("À implémenter dans une classe fille") Livraison().calculer_frais() # NotImplementedError: À implémenter dans une classe fille
À noter
On retourne NotImplemented, on lève NotImplementedError.
Que fait Python quand il reçoit NotImplemented ?
Comme je le disais plus haut, Python tente l'opération dans l'autre sens avec la méthode réfléchie de l'autre objet. Par exemple, __radd__ pour +.
class Panier: def __init__(self, articles): self.articles = articles def __repr__(self): return f"Panier({self.articles})" def __add__(self, autre): print("Panier.__add__ appelée") if not isinstance(autre, Panier): return NotImplemented return Panier(self.articles + autre.articles) class Cadeau: def __init__(self, nom): self.nom = nom def __radd__(self, autre): print("Cadeau.__radd__ appelée") return Panier(autre.articles + [self.nom]) panier_patrick = Panier(["pommes", "lait"]) print(panier_patrick + Cadeau("chocolats")) # Panier.__add__ appelée # Cadeau.__radd__ appelée # Panier(['pommes', 'lait', 'chocolats'])
Inscrivez-vous gratuitement pour modifier et exécuter du code Python directement dans votre navigateur.
Sébastien est tellement sympa qu'il glisse un cadeau dans le panier de Patrick. La méthode __add__ de Panier ne connaît pas Cadeau et renvoie NotImplemented. Python se replie alors vers la méthode __radd__ de Cadeau, qui sait quoi faire.
Si personne ne sait quoi faire, Python lèvera une exception TypeError.
À noter
Pour ==, le dernier recours n'est pas une exception : Python compare l'identité des deux objets et renvoie False.