web-dev-qa-db-fra.com

Python essayer finalement de bloquer les retours

Il y a le code intéressant ci-dessous:

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

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

func1()
func2()

Quelqu'un pourrait-il expliquer, quels résultats renverront ces deux fonctions et expliquer pourquoi, c.-à-d. Décrire l’ordre d’exécution

53
skybobbi

De la Python documentation

Une clause finally est toujours exécutée avant de quitter l'instruction try, qu'une exception soit survenue ou non. Lorsqu'une exception s'est produite dans la clause try et qu'elle n'a pas été gérée par une clause except (ou qu'elle s'est produite dans une clause except ou else), elle est à nouveau déclenchée après l'exécution de la clause finally. La clause finally est également exécutée "à la sortie" lorsqu'une autre clause de l'instruction try est laissée via une instruction break, continue ou return . Un exemple plus compliqué (avoir les clauses except et finally dans la même instruction try fonctionne à partir de Python 2.5):

Donc, une fois que le bloc try/except est quitté, utilisez return , ce qui définirait la valeur de retour comme étant donné - les blocs finiront par toujours exécuter, et devrait être utilisé pour libérer des ressources, etc. tout en utilisant un autre retour - écrase le premier.

Dans votre cas particulier, func1() return 2 Et func2() return 3, Car il s'agit de valeurs renvoyées dans les blocs finally.

99
lejlot

Il ira toujours dans le bloc finally, donc il ignorera le return dans les try et except. Si vous aviez return au-dessus de try et except, il renverrait cette valeur.

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
29
user1408786

Mettre les déclarations print à l'avance aide vraiment, aide vraiment:

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\'s return 3'
        return 3

print func1()
print func2()

Cela retourne:

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's return 3
3

Vous remarquerez que python renvoie toujours la dernière chose à retourner, même si le code "atteint" return 1 dans les deux fonctions.

Un bloc finally est toujours exécuté, la dernière chose à renvoyer dans la fonction est donc ce qui est retourné dans le bloc finally. Dans func1, ça fait 2. Dans func2, c'est 3.

7
TerryA

func1() renvoie 2. func2() renvoie 3.

finally le bloc est exécuté finalement quelle que soit l'exception.

Vous pouvez voir l'ordre d'exécution à l'aide du débogueur. Par exemple, voir n screencast .

1
falsetru