Python попытается окончательно вернуть блок
Ниже приведен интересный код:
def func1():
try:
return 1
finally:
return 2
def func2():
try:
raise ValueError()
except:
return 1
finally:
return 3
func1()
func2()
Может кто-нибудь объяснить, какие результаты будут возвращать эти две функции и объяснить, почему, то есть описать порядок выполнения
Ответы
Ответ 1
Из документации Python
Предложение finally всегда выполняется перед выходом из оператора try независимо от того, произошло исключение или нет. Если исключение произошло в предложении try и не было обработано предложением exc (или оно возникло в предложении исключения или else), оно повторно вызывается после выполнения предложения finally. Предложение finally также выполняется "на выходе", когда любое другое предложение оператора try оставляется с помощью оператора break, continue или return. Более сложный пример (с предложениями exc и finally в том же операторе try, что и в Python 2.5):
Таким образом, после того, как блок try/exception будет оставлен с использованием return, что установит возвращаемое значение в заданный - в конце концов блоки будут всегда выполняться и должны использоваться для освобождения ресурсов и т.д. При использовании есть еще один возврат - переписывает исходный.
В вашем конкретном случае, func1()
возвращает 2
, а func2()
возвращает 3
, так как это значения, возвращаемые в блоках finally.
Ответ 2
Он всегда будет идти в блок finally
, поэтому он будет игнорировать return
в try
и except
. Если бы вы имели return
выше try
и except
, он вернул бы это значение.
def func1():
try:
return 1 # ignoring the return
finally:
return 2 # returns this return
def func2():
try:
raise ValueError()
except:
# is going to this exception block, but ignores the return because it needs to go to the finally
return 1
finally:
return 3
def func3():
return 0 # finds a return here, before the try except and finally block, so it will use this return
try:
raise ValueError()
except:
return 1
finally:
return 3
func1() # returns 2
func2() # returns 3
func3() # returns 0
Ответ 3
Полагая инструкции print
заранее, действительно помогает:
def func1():
try:
print 'try statement in func1. after this return 1'
return 1
finally:
print 'after the try statement in func1, return 2'
return 2
def func2():
try:
print 'raise a value error'
raise ValueError()
except:
print 'an error has been raised! return 1!'
return 1
finally:
print 'okay after all that let\ return 3'
return 3
print func1()
print func2()
Это возвращает:
try statement in func1. after this return 1
after the try statement in func1, return 2
2
raise a value error
an error has been raised! return 1!
okay after all that let return 3
3
Вы заметите, что python всегда возвращает последнее, что нужно вернуть, независимо от того, что код "достиг" return 1
в обеих функциях.
A finally
выполняется всегда, поэтому последнее, что нужно вернуть в функции, - это то, что возвращается в блоке finally. В func1
, что 2. В func2
, что 3.
Ответ 4
func1()
возвращает 2. func2()
возвращает 3.
finally
блок выполняется окончательно независимо или исключение.
Вы можете увидеть порядок выполнения с помощью отладчика. Например, см. скринкаст.