Вопрос

Я нашел по крайней мере следующее поведение странный:

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

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

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

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

Это было полезно?

Решение

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

Другие советы

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

Это:

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

Вот интересное сравнение возврата в блоке Final среди Java/C#/Python/JavaScript:(ссылка на архив)

Вернуться из наконец

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

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

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

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

Питон:

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 нет предложения, поэтому я не могу попробовать последние два языка, для которых у меня есть компилятор/интерпретатор.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top