возврат ест исключение
Вопрос
Я нашел по крайней мере следующее поведение странный:
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
, поэтому я предполагаю, что один будет возвращен.Однако это не случай:Я понимаю, что логика, наконец, должна быть выполнена раздел, но почему -то я чувствую себя неловко по этому поводу.Давайте посмотрим, что делает 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()); } }
Я предпочитаю такое поведение, поток управления нельзя испортить в предложении finally, так что это не позволяет нам стрелять в себя в нога.Просто для полноты картины давайте проверим, какие другие Языки делают.
Питон:
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>
В C ++ и PHP нет предложения, поэтому я не могу попробовать последние два языка, для которых у меня есть компилятор/интерпретатор.
Наш небольшой эксперимент показал, что C# имеет самый лучший подход к этой проблеме, но я был весьма удивлен, узнав, что все Другие языки решают эту проблему таким же образом.
Возвращение из наконец-то нет хорошая идея.Я знаю, что C# специально запрещает это делать.