web-dev-qa-db-fra.com

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

Il s'agit d'un code qui se comporte de façon particulière. Il s'agit d'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émo 1 renvoie 3 au lieu de 1?
  • Pourquoi la démo deux imprime-t-elle 6 au lieu d'imprimer 6 avec 4 ou 5?
72
Kyle Owens

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

L'état documents 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 raison est un problème avec la mise en œuvre actuelle - cette restriction pourrait être levée à l'avenir).

Cela signifie que lorsque vous essayez de retourner, le bloc finally est appelé, retournant sa valeur, plutôt que celui que vous auriez eu.

105
Gareth Latty

L'ordre d'exécution est le suivant:

  1. essayer bloquer tout se termine normalement -> enfin bloquer -> la fonction se termine
  2. essayez l'exécution de bloc et entrez dans l'exception A -> enfin bloc -> la fonction se termine
  3. essayez bloc faire une valeur de retour et appelez retour -> enfin bloc -> valeur de retour popup -> la fonction se termine

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

5
Fred Huang