Warum NotImplemented zurückgeben, anstatt NotImplementedError auszulösen?

282

Python hat einen Singleton namens NotImplemented.

Warum sollte jemand jemals zurückkehren wollen, NotImplementedanstatt die NotImplementedErrorAusnahme auszulösen? Wird es nicht nur schwieriger sein, Fehler zu finden, z. B. Code, der ungültige Methoden ausführt?

Abyx
quelle

Antworten:

281

Dies liegt daran, dass __lt__()verwandte Vergleichsmethoden häufig indirekt in Listensortierungen und dergleichen verwendet werden. Manchmal wählt der Algorithmus einen anderen Weg oder einen Standardsieger. Das Auslösen einer Ausnahme würde aus der Sortierung ausbrechen, sofern sie nicht abgefangen wird, während NotImplementedsie nicht ausgelöst wird und für weitere Tests verwendet werden kann.

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

Um diesen Link zusammenzufassen:

" NotImplementedSignale an die Laufzeit , dass es jemanden fragen sollte sonst den Betrieb gerecht zu werden. In dem Ausdruck a == b, wenn a.__eq__(b)zurückkehrt NotImplemented, dann versucht Python b.__eq__(a). Wenn bgenug wissen , um zurückzukehren Trueoder False, dann kann der Ausdruck erfolgreich zu sein. Wenn nicht, dann ist die Laufzeit wird auf das eingebaute Verhalten zurückgreifen (das auf der Identität für ==und basiert !=). "

SpliFF
quelle
5
Ich würde vorsichtig damit umgehen, da dieser Link gegen Ende des Dokuments verweist.
Jason Coon
16
Wenn der Python-Interpreter prüft, ob a.__eq__(b)NotImplemented zurückgegeben wird, kann er dann nicht genauso einfach NotImplementedError abfangen (und dann aufrufen b.__eq__(a)oder was auch immer)?
Veky
24
@ Veky. Das Auslösen einer Ausnahme hat wahrscheinlich einen höheren Overhead. Jeder Aufwand bei einer Sortieroperation wird durch die Größe der Liste vergrößert. Selbst wenn der Unterschied sehr gering wäre, wäre es dennoch sinnvoll, eine schnellere Implementierung zu finden. Sie möchten auch nicht aus Ihren Schleifen ausbrechen und sie erneut eingeben, was für eine Try / Catch-Implementierung erforderlich wäre.
SpliFF
3
Für den ersten Punkt wäre eine noch schnellere Lösung, lt automatisch als umgekehrtes gt zu synthetisieren, anstatt immer etwas aufzurufen, das NotImplemented zurückgibt - und Python tut das nicht. Ich denke nicht, dass Geschwindigkeit der Grund hier ist. Und zum zweiten verstehe ich nicht, was Sie sagen: Für die Rückkehr muss genauso viel aus den Schleifen herausgebrochen werden wie für das Erhöhen. Tatsächlich können Sie sich vorstellen, dass return eine spezielle Return-Ausnahme auslöst, die immer im aufrufenden Bereich abgefangen wird.
Veky
2
>> "vergrößert durch die Größe der Liste" Zumindest, wenn Sie keine O (n) -Sorte haben, über die die Welt Bescheid wissen sollte.
Jonathan Hartley
106

Weil sie unterschiedliche Anwendungsfälle haben.

Zitieren der Dokumente (Python 3.6):

Nicht implementiert

sollte durch die binären speziellen Methoden (zB zurückgegeben werden __eq__(), __lt__(), __add__(), __rsub__(), etc.) , um anzuzeigen , dass die Operation nicht in Bezug auf die andere Art durchgeführt wird

Ausnahme NotImplementedError

[...] In benutzerdefinierten Basisklassen sollten abstrakte Methoden diese Ausnahme auslösen, wenn abgeleitete Klassen zum Überschreiben der Methode erforderlich sind oder während die Klasse entwickelt wird, um anzuzeigen, dass die tatsächliche Implementierung noch hinzugefügt werden muss.

Siehe die Links für Details.

Paolo
quelle
13

Ein Grund ist die Leistung. In einer Situation wie umfangreichen Vergleichen, in der Sie in kurzer Zeit viele Vorgänge ausführen können, kann das Einrichten und Behandeln vieler Ausnahmen viel länger dauern als die einfache Rückgabe eines NotImplementedWerts.

RichieHindle
quelle