Comportement étrange Try-Except-Else-Then avec les instructions Return

88

C'est un code qui se comporte de façon particulière. Ceci est une version simplifiée du comportement que j'ai écrit. Cela démontrera toujours le comportement étrange et j'avais des questions spécifiques sur la raison pour laquelle cela se produit.

J'utilise Python 2.6.6 sur Windows 7.

def demo1():
    try:
        raise RuntimeError,"To Force Issue"
    except:
        return 1
    else:
        return 2
    finally:
        return 3

def demo2():
    try:
        try:
            raise RuntimeError,"To Force Issue"
        except:
            return 1
        else:
            return 2
        finally:
            return 3
    except:
        print 4
    else:
        print 5
    finally:
        print 6

Résultats:

>>> print demo1()
3
>>> print demo2()
6
3
  • Pourquoi la démonstration 1 renvoie-t-elle 3 au lieu de 1?
  • Pourquoi la démo deux imprime-t-elle 6 au lieu d'imprimer 6 w / 4 ou 5?
Kyle Owens
la source

Réponses:

124

Parce que les finallyinstructions sont garanties pour être exécutées (enfin, en supposant qu'aucune panne de courant ou quoi que ce soit en dehors du contrôle de Python). Cela signifie qu'avant que la fonction puisse retourner, elle doit exécuter le bloc finally, qui renvoie une valeur différente.

L' état de la documentation Python :

Lorsqu'une instruction return, break ou continue est exécutée dans la suite try d'une instruction try… finally, la clause finally est également exécutée «à la sortie».

La valeur de retour d'une fonction est déterminée par la dernière instruction de retour exécutée. Puisque la clause finally s'exécute toujours, une instruction return exécutée dans la clause finally sera toujours la dernière exécutée:

Cela signifie que lorsque vous essayez de revenir, le finallybloc est appelé, renvoyant sa valeur, plutôt que celle que vous auriez eue.

Gareth Latty
la source
4
pourquoi le 5 ne s'imprime-t-il pas dans le deuxième exemple? ce n'est toujours pas bien expliqué je pense. le retour est bien répondu, mais pourquoi le 5 dans le deuxième exemple n'est pas imprimé
Joran Beasley
5
oh je pense que j'ai compris que le retour dans l'essai initial le fait sauter immédiatement à l'extérieur enfin
Joran Beasley
2
Exactement, car les finallyblocs fonctionnent toujours .
Gareth Latty
2
Dans la démo deux, pourquoi exécute-t-il enfin le niché, expulse enfin vers l'extérieur puis retourne enfin dans le niché pour terminer le retour au lieu de simplement renvoyer None de l'extérieur enfin?
Kyle Owens
1
Parce que lorsque l' returninstruction est appelée, Python vérifie toutes les finallyclauses ouvertes qui doivent être exécutées (voir la citation ci-dessus).
Gareth Latty
6

L'ordre d'exécution est:

  1. try block all se termine normalement -> finally block -> la fonction se termine
  2. essayez le block run et entrez dans l'exception A -> finally block -> la fonction se termine
  3. try block crée une valeur de retour et appelle return -> finally block -> popup return value -> function ends

Ainsi, tout retour dans le bloc finally mettra fin aux étapes à l'avance.

Fred Huang
la source