возврат ест исключение - PullRequest
       10

возврат ест исключение

26 голосов
/ 05 февраля 2009

Я обнаружил следующее поведение как минимум странно :

def errors():
    try:
        ErrorErrorError
    finally:
        return 10

print errors()
# prints: 10
# It should raise: NameError: name 'ErrorErrorError' is not defined

Исключение исчезает, когда вы используете return внутри предложения finally. Это ошибка? Это где-нибудь задокументировано?

Но реальный вопрос (и ответ, который я отмечу как правильный):
По какой причине разработчики Python допускают такое странное поведение?

Ответы [ 4 ]

54 голосов
/ 05 февраля 2009

Исключение исчезает, когда вы используете return внутри предложения finally. .. Это где-нибудь задокументировано?

Это:

Если, наконец, присутствует, он определяет обработчик очистки. Предложение try выполняется, в том числе любые исключения и другие. Если исключение возникает в каком-либо из пунктов и не обрабатывается, исключение временно сохраняется. Предложение finally выполняется. Если есть сохраненное исключение, оно повторно вызывается в конце предложения finally. Если предложение finally вызывает другое исключение или выполняет оператор return или break, сохраненное исключение теряется.

35 голосов
/ 08 февраля 2009

Вы спрашивали о рассуждениях разработчиков Python. Я не могу говорить за них, но никакое другое поведение не имеет смысла. Функция может либо вернуть значение, либо вызвать исключение; это не может сделать оба. Цель предложения «finally» - предоставить код очистки, который «гарантированно» будет запущен независимо от исключений. Поместив оператор return в предложение finally, вы объявили, что хотите вернуть значение, несмотря ни на что, независимо от исключений. Если бы Python вел себя так, как вы просили, и вызвал исключение, это нарушило бы контракт предложения "finally" (потому что он не смог бы вернуть значение, которое вы сказали ему возвращать).

4 голосов
/ 06 февраля 2009

Вот интересное сравнение для возврата в блок finally, среди - Java / C # / Python / JavaScript: http://www.gettingclever.com/2008/07/return-from-finally.html

РЕДАКТИРОВАТЬ: Ссылка не работает. Скопировано здесь с https://web.archive.org/web/20120426091446/http://www.gettingclever.com/2008/07/return-from-finally.html:

Возвращение наконец

Только сегодня я помогал с некоторой ошибкой в ​​Java и наткнулся на интересная проблема - что произойдет, если вы используете return в try / catch заявление? Должен ли наконец-то запускаться раздел или нет? Я упростила проблема в следующем фрагменте кода:

Что выводит следующий код?

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());  
        }  
}  

Мое первоначальное предположение было бы, что это должно распечатать 1, я звоню return, поэтому я предполагаю, что один будет возвращен. Тем не менее, это не случай:

the second return is executed

Я понимаю логику, наконец, раздел должен быть выполнен, но как-то мне неловко по этому поводу. Давайте посмотрим, что C # делает в этом случае:

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());  
 }  
}  

error CS0157 Control cannot leave the body of a finally clause

Я предпочитаю гораздо больше такое поведение, поток управления не может быть перепутан с в конечном итоге, так что это мешает нам застрелиться в ступня. Просто для полноты давайте проверим, что еще языки делают.

Python:

def a():  
 try:  
  return 1  
 finally:  
  return 2  
print a()  

Python returns 2 as well

JavaScript:

<script>  
function ReturnFromFinally()  
{  
 try  
 {  
  return 1;  
 }  
 catch (e)  
 {  
 }  
 finally  
 {  
  return 2;  
 }  
}  
</script>  
<a onclick="alert(ReturnFromFinally());">Click here</a>  

JavaScript returns 2 as well

В C ++ и PHP нет предложения finally, поэтому я не могу опробовать последнее два языка, для которых у меня есть компилятор / интерпретатор.

Наш маленький эксперимент хорошо показал, что C # имеет лучший подход к этой проблеме, но я был весьма удивлен, узнав, что все другие языки решают проблему таким же образом.

3 голосов
/ 05 февраля 2009

Возвращение от наконец-то не хорошая идея. Я знаю, что C # специально запрещает это делать.

...