Perché restituire NotImplemented invece di sollevare NotImplementedError


283

Python ha un singleton chiamato NotImplemented.

Perché qualcuno dovrebbe mai voler tornare NotImplementedinvece di sollevare l' NotImplementedErroreccezione? Non sarà solo più difficile trovare bug, come il codice che esegue metodi non validi?

Risposte:


281

È perché __lt__()e i metodi di confronto correlati sono abbastanza comunemente usati indirettamente negli elenchi e simili. A volte l'algoritmo sceglierà di provare in un altro modo o scegliere un vincitore predefinito. Sollevare un'eccezione uscirebbe dal genere se non catturato, mentre NotImplementednon viene sollevato e può essere utilizzato in ulteriori test.

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

Per riassumere quel link:

" NotImplementedsegnala al runtime che dovrebbe chiedere a qualcun altro di soddisfare l'operazione. Nell'espressione a == b, se a.__eq__(b)ritorna NotImplemented, Python prova b.__eq__(a). Se ne bsa abbastanza per tornare Trueo False, allora l'espressione può avere successo. In caso contrario, il runtime ricadere nel comportamento predefinito (che si basa sull'identità di ==e !=). "


5
Starei attento a usarlo, poiché questo link sottolinea verso la fine del documento.
Jason Coon,

16
Quando l'interprete di Python verifica se a.__eq__(b)restituito NotImplemented, non potrebbe facilmente catturare invece NotImplementedError (e chiamare b.__eq__(a)o comunque)?
Veky,

24
@Veky. Generare un'eccezione probabilmente ha un overhead più elevato. Qualsiasi overhead in un'operazione di ordinamento verrà ingrandito dalla dimensione dell'elenco, quindi anche se la differenza fosse molto piccola avrebbe comunque senso trovare un'implementazione più veloce. Inoltre, non si desidera uscire dai propri loop e inserirli di nuovo nel modo richiesto da un'implementazione try / catch.
SpliFF,

3
Per il primo punto, una soluzione ancora più veloce sarebbe quella di sintetizzare automaticamente lt come gt invertita, invece di chiamare sempre qualcosa che restituirà NotImplemented - e Python non lo fa. Non penso che la velocità sia la ragione qui. E per il secondo, non capisco quello che stai dicendo: il ritorno richiederà lo stesso superamento dei cicli di rilancio. In effetti, puoi immaginare il ritorno come sollevare una speciale eccezione di ritorno, che viene sempre catturata nell'ambito della chiamata.
Veky,

2
>> "ingigantito dalla dimensione della lista" Almeno, a meno che tu non abbia una O (n) specie che il mondo dovrebbe conoscere.
Jonathan Hartley,

107

Perché hanno diversi casi d'uso.

Citando i documenti (Python 3.6):

Non implementato

deve essere restituito dai metodi speciali binari (ad esempio __eq__(), __lt__(), __add__(), __rsub__(), etc.) per indicare che l'operazione non è implementata rispetto all'altro tipo

eccezione NotImplementedError

[...] Nelle classi base definite dall'utente, i metodi astratti dovrebbero sollevare questa eccezione quando richiedono che le classi derivate abbiano la precedenza sul metodo o mentre la classe è in fase di sviluppo per indicare che è ancora necessario aggiungere l'implementazione reale.

Vedi i link per i dettagli.


Questa dovrebbe essere la risposta accettata. È anche più forte dei casi d'uso, è un'indicazione di intento: quello con Errore alla fine del nome segnala che si è verificato un Errore (perché qualcosa non è implementato), l'altro non è un errore ma "corretto" comportamento. Vorrei paragonarlo alla differenza tra restituire NaN o aumentare un ValueError.
Korone

13

Uno dei motivi è la prestazione. In una situazione come un confronto approfondito, in cui è possibile eseguire molte operazioni in breve tempo, l'impostazione e la gestione di molte eccezioni potrebbe richiedere molto più tempo rispetto alla semplice restituzione di un NotImplementedvalore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.