Подтвердить что ты не робот

Python попытается окончательно вернуть блок

Ниже приведен интересный код:

def func1():
    try:
        return 1
    finally:
        return 2

def func2():
    try:
        raise ValueError()
    except:
        return 1
    finally:
        return 3

func1()
func2()

Может кто-нибудь объяснить, какие результаты будут возвращать эти две функции и объяснить, почему, то есть описать порядок выполнения

4b9b3361

Ответ 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 блок выполняется окончательно независимо или исключение.

Вы можете увидеть порядок выполнения с помощью отладчика. Например, см. скринкаст.