Pourquoi renvoyer NotImplemented au lieu de déclencher NotImplementedError


283

Python a un singleton appelé NotImplemented.

Pourquoi voudrait-on jamais revenir NotImplementedau lieu de soulever l' NotImplementedErrorexception? Cela ne rendra-t-il pas simplement plus difficile la recherche de bogues, tels que le code qui exécute des méthodes invalides?

Réponses:


281

C'est parce __lt__()que les méthodes de comparaison associées sont assez couramment utilisées indirectement dans les sortes de listes et autres. Parfois, l'algorithme choisira d'essayer d'une autre manière ou de choisir un gagnant par défaut. La levée d'une exception sortirait du cadre à moins d'être interceptée, alors qu'elle NotImplementedn'est pas levée et peut être utilisée dans d'autres tests.

http://jcalderone.livejournal.com/32837.html

Pour résumer ce lien:

" NotImplementedsignale au runtime qu'il doit demander à quelqu'un d'autre de satisfaire l'opération. Dans l'expression a == b, si a.__eq__(b)retourne NotImplemented, alors Python essaie b.__eq__(a). S'il en bsait assez pour retourner Trueou False, alors l'expression peut réussir. Si ce n'est pas le cas, alors le runtime retomber dans le comportement intégré (qui est basé sur l'identité pour ==et !=). "


5
Je serais prudent en l'utilisant, comme le montre ce lien vers la fin du document.
Jason Coon,

16
Lorsque l'interpréteur Python vérifie s'il a a.__eq__(b)renvoyé NotImplemented, ne pourrait-il pas tout aussi facilement attraper NotImplementedError à la place (et appeler b.__eq__(a)ou autre chose alors)?
Veky

24
@Veky. La levée d'une exception a probablement un surcoût plus élevé. Toute surcharge dans une opération de tri sera agrandie par la taille de la liste, donc même si la différence était très petite, il serait toujours logique de trouver une implémentation plus rapide. Vous ne voulez pas non plus sortir de vos boucles et les ressaisir, ce qui nécessiterait une implémentation try / catch.
SpliFF

3
Pour le premier point, une solution encore plus rapide serait de synthétiser automatiquement lt en gt inversé, au lieu d'appeler toujours quelque chose qui retournera NotImplemented - et Python ne le fait pas. Je ne pense pas que la vitesse soit la raison ici. Et pour le second, je ne comprends pas ce que vous dites: le retour nécessitera autant de rupture de boucles que l'augmentation. En fait, vous pouvez imaginer return comme levant une exception Return spéciale, qui est toujours interceptée dans la portée d'appel.
Veky

2
>> "agrandi par la taille de la liste" Du moins, sauf si vous avez un tri O (n) que le monde devrait connaître.
Jonathan Hartley

107

Parce qu'ils ont des cas d'utilisation différents.

Citant les documents (Python 3.6):

Pas mis en œuvre

doivent être retournés par les méthodes spéciales binaires (par exemple __eq__(), __lt__(), __add__(), __rsub__(), etc.) pour indiquer que l'opération ne soit pas mis en œuvre par rapport à l'autre type

exception NotImplementedError

[...] Dans les classes de base définies par l'utilisateur, les méthodes abstraites devraient lever cette exception lorsqu'elles nécessitent que les classes dérivées remplacent la méthode, ou pendant le développement de la classe pour indiquer que l'implémentation réelle doit encore être ajoutée.

Voir les liens pour plus de détails.


Ce devrait être la réponse acceptée. C'est encore plus fort que les cas d'utilisation, c'est une indication d'intention - celui avec Erreur à la fin du nom signale qu'une Erreur s'est produite (parce que quelque chose n'est pas implémenté), l'autre n'est pas une erreur mais "propre" comportement. Je comparerais cela à la différence entre retourner NaN ou lever une ValueError.
Korone Il y a

13

L'une des raisons est la performance. Dans une situation comme les comparaisons riches, où vous pouvez effectuer de nombreuses opérations en peu de temps, la configuration et la gestion de nombreuses exceptions peuvent prendre beaucoup plus de temps que le simple retour d'une NotImplementedvaleur.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.