Por que retornar NotImplemented em vez de aumentar NotImplementedError

282

Python tem um singleton chamado NotImplemented.

Por que alguém iria querer voltar em NotImplementedvez de criar a NotImplementedErrorexceção? Não apenas tornará mais difícil encontrar erros, como código que executa métodos inválidos?

abyx
fonte

Respostas:

281

É porque __lt__()métodos de comparação relacionados são comumente usados ​​indiretamente em tipos de lista e coisas do tipo. Às vezes, o algoritmo decide tentar de outra maneira ou escolher um vencedor padrão. Gerar uma exceção seria diferente, a menos que detectado, enquanto NotImplementednão é gerado e pode ser usado em outros testes.

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

Para resumir esse link:

" NotImplementedsinaliza ao tempo de execução que ele deve solicitar a outra pessoa que satisfaça a operação. Na expressão a == b, se a.__eq__(b)retorna NotImplemented, o Python tenta b.__eq__(a). Se bsouber o suficiente para retornar Trueou False, a expressão poderá ser bem-sucedida. Se não, o tempo de execução será voltar ao comportamento interno (que é baseado na identidade para ==e !=). "

SpliFF
fonte
5
Eu tomaria cuidado ao usá-lo, pois esse link aponta próximo ao final do documento.
1811 Jason Coon
16
Quando o intérprete Python verifica se o a.__eq__(b)NotImplemented retornado, ele não poderia facilmente capturar o NotImplementedError (e chamar b.__eq__(a)ou o que quer que seja)?
Veky
24
@Veky. Gerar uma exceção provavelmente tem uma sobrecarga mais alta. Qualquer sobrecarga em uma operação de classificação será ampliada pelo tamanho da lista, portanto, mesmo que a diferença fosse muito pequena, ainda faria sentido encontrar uma implementação mais rápida. Você também não deseja interromper seus loops e reinseri-los, o que exigiria uma implementação try / catch.
SpliFF
3
Para o primeiro ponto, uma solução ainda mais rápida seria sintetizar automaticamente lt como gt invertido, em vez de sempre chamar algo que retornará NotImplemented - e o Python não faz isso. Eu não acho que a velocidade é a razão aqui. E, para o segundo, não entendo o que você está dizendo: o retorno exigirá tanto rompimento de loops quanto o aumento. De fato, você pode imaginar return como gerando uma exceção Return especial, que é sempre detectada no escopo da chamada.
Veky
2
>> "ampliada pelo tamanho da lista" Pelo menos, a menos que você tenha uma classificação O (n) que o mundo deveria conhecer.
9788 Jonathan
106

Porque eles têm diferentes casos de uso.

Citando os documentos (Python 3.6):

Não implementado

devem ser devolvidos pelos métodos especiais binários (por exemplo __eq__(), __lt__(), __add__(), __rsub__(), etc.) para indicar que a operação não é implementado em relação ao outro tipo

exceção NotImplementedError

[...] Nas classes base definidas pelo usuário, os métodos abstratos devem gerar essa exceção quando exigem que as classes derivadas substituam o método ou enquanto a classe está sendo desenvolvida para indicar que a implementação real ainda precisa ser adicionada.

Veja os links para detalhes.

Paolo
fonte
13

Um dos motivos é o desempenho. Em uma situação como comparações ricas, em que você pode realizar muitas operações em pouco tempo, configurar e manipular muitas exceções pode levar muito mais tempo do que simplesmente retornar um NotImplementedvalor.

RichieHindle
fonte