exceção retorno come
Pergunta
Eu encontrei o seguinte comportamento, pelo menos, estranho :
def errors():
try:
ErrorErrorError
finally:
return 10
print errors()
# prints: 10
# It should raise: NameError: name 'ErrorErrorError' is not defined
A exceção desaparece quando você usa return
dentro de uma cláusula finally
. Isso é um bug? É isso documentado em qualquer lugar?
Mas a questão real (e a resposta que irá marcar como correto) é:
Qual é a razão dos desenvolvedores do Python para permitir que o comportamento estranho?
Solução
Você perguntou sobre o raciocínio dos desenvolvedores do Python. Eu não posso falar por eles, mas nenhum outro comportamento faz sentido. Uma função pode devolver um valor, ou pode gerar uma exceção; ele não pode fazer as duas coisas. O objectivo da cláusula "finalmente" é fornecer o código de limpeza que está "garantido" para ser executado, independentemente de exceções. Ao colocar um instrução de retorno em uma cláusula finalmente, você declarou que deseja retornar um valor, não importa o que, independentemente de exceções. Se Python se comportou como você está pedindo e levantou a exceção, ele estaria quebrando o contrato do "finalmente" cláusula (porque isso não devolver o valor que você disse que ele retorne).
Outras dicas
A exceção desaparece quando você usa
return
dentro de uma cláusulafinally
. .. Isso é documentado em qualquer lugar?
Se finalmente está presente, ele especifica um manipulador de ‘limpeza’. A cláusula try é executado, incluindo qualquer exceto e cláusulas else. Se ocorrer uma exceção em qualquer das cláusulas e não é tratada, a exceção é salva temporariamente. A cláusula finally é executada. Se houver uma exceção salvo, ele é re-levantada no final da cláusula finally. Se a cláusula finally levanta outra exceção ou executa uma instrução de retorno ou quebra, a exceção salvo é perdido.
Aqui está uma comparação interessante para o retorno no bloco finally, entre - Java / C # / Python / JavaScript: ( arquivo de ligação )
Retorno De Finalmente
Só hoje eu estava ajudando com algum bug em Java e me deparei problema interessante - o que acontece se você usar o retorno dentro de try / catch declaração? Caso a secção finalmente fogo-se ou não? I simplificou o problema a seguinte trecho de código:
O que significa o seguinte código imprimir?
class ReturnFromFinally { public static int a() { try { return 1; } catch (Exception e) {} finally{ return 2; } } public static void main(String[] args) { System.out.println(a()); } }
Meu palpite inicial seria, que deve imprimir
1
, eu estou chamandoreturn
, assim que eu supor, um será devolvido. No entanto, não é a caso:Eu entendo a lógica, finalmente secção tem de ser executado, mas de alguma forma eu me sinto desconfortável com isso. Vamos ver o que C # faz neste caso:
class ReturnFromFinally { public static int a() { try { return 1; } catch (System.Exception e) {} finally { return 2; } } public static void Main(string[] args) { System.Console.WriteLine(a()); } }
Eu prefiro muito mais esse comportamento, controle de fluxo não pode ser mexido com na cláusula finally, por isso nos impede de disparar a nós mesmos no pé. Apenas por uma questão de exaustividade, vamos verificar o que outros línguas fazer.
Python:
def a(): try: return 1 finally: return 2 print a()
JavaScript:
<script> function ReturnFromFinally() { try { return 1; } catch (e) { } finally { return 2; } } </script> <a onclick="alert(ReturnFromFinally());">Click here</a>
Não há nenhuma cláusula finally em C ++ e PHP, então eu não posso experimentar a última duas línguas tenho compilador / intérprete para.
A nossa pequena experiência bem mostrou, que o C # tem a abordagem mais agradável para este problema, mas eu estava muito surpreso ao saber, que todo o outras línguas lidar com o problema da mesma forma.
Retornando de uma finalmente é não uma boa idéia. Eu sei C # especificamente proíbe de fazer isso.