Existe uma diferença entre “levantar exceção ()” e “levantar exceção” sem parênteses?

99

Definindo uma exceção sem parâmetros:

class MyException(Exception):
    pass

Quando criado, há alguma diferença entre:

raise MyException

e

raise MyException()

Não consegui encontrar nenhum; é simplesmente uma sintaxe sobrecarregada?

Ohad Dan
fonte
1
Leia esta resposta: stackoverflow.com/questions/13052991/…
satoru
1
Estritamente falando, não é sintático. Python não pode saber se obterá uma classe ou instância até o tempo de execução.
asmeurer em

Respostas:

114

A resposta curta é que ambos raise MyException e raise MyException()fazem a mesma coisa. Este primeiro formulário cria uma instância automática de sua exceção.

A seção relevante dos documentos diz: " raise avalia a primeira expressão como o objeto de exceção. Deve ser uma subclasse ou uma instância de BaseException. Se for uma classe, a instância de exceção será obtida quando necessário instanciando a classe com sem argumentos. "

Dito isso, embora a semântica seja a mesma, a primeira forma é microscopicamente mais rápida e a segunda forma é mais flexível (porque você pode passar argumentos, se necessário).

O estilo usual que a maioria das pessoas usa em Python (ou seja, na biblioteca padrão, em aplicativos populares e em muitos livros) é raise MyExceptionquando não há argumentos. As pessoas apenas instanciam a exceção diretamente quando alguns argumentos precisam ser passados. Por exemplo: raise KeyError(badkey).

Raymond Hettinger
fonte
18
Por que a primeira forma (sem parênteses) seria microscopicamente mais rápida?
Jamesdlin
15
@jamesdlin Porque o código C para auto-instanciar não tem a sobrecarga interpretada que vem de você mesmo fazer a chamada.
Raymond Hettinger,
4

Vá dar uma olhada na documentação da raisedeclaração . Ele está criando uma instância de MyException.

Jason Fried
fonte
1
É importante notar que a sintaxe deraise mudou um pouco no Python 3. A parte que é relevante para esta questão é a mesma ( raise ExceptionTypeainda cria uma instância do tipo chamando seu construtor sem argumentos).
Blckknght
0

Sim, há uma diferença entre ValueErroreValueError()

ValueErroré uma classe enquanto ValueError()cria uma instância de uma classe. Esta é a razão pela qual type(ValueError) is typeetype(ValueError()) is ValueError

O único objetivo de raiseé levantar a exceção,

quando usarmos ValueError, a classe será chamada, que por sua vez executa o construtor ValueError()

quando usamos ValueError(), o método ValueError()é chamado diretamente.

Nota: raise ValueError # shorthand for 'raise ValueError()'

Ranjith Udayakumar
fonte