Strano comportamento Try-Except-Else-Finalmente con istruzioni Return


91

Questo è un codice che si comporta in modo particolare. Questa è una versione semplificata del comportamento che ho scritto. Ciò dimostrerà ancora il comportamento strano e avevo alcune domande specifiche sul motivo per cui ciò si verifica.

Sto usando Python 2.6.6 su 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

Risultati:

>>> print demo1()
3
>>> print demo2()
6
3
  • Perché la demo uno restituisce 3 invece di 1?
  • Perché la demo due stampa 6 invece di stampare 6 con 4 o 5?

Risposte:


128

Perché finallyè garantito che le istruzioni vengano eseguite (beh, presumendo che non vi siano interruzioni di corrente o altro al di fuori del controllo di Python). Ciò significa che prima che la funzione possa tornare, deve eseguire il blocco finalmente, che restituisce un valore diverso.

La documentazione di Python afferma:

Quando un'istruzione return, break o continue viene eseguita nella suite try di un'istruzione try ... infine, viene eseguita anche la clausola finalmente "in uscita".

Il valore restituito di una funzione è determinato dall'ultima istruzione return eseguita. Poiché la clausola finalmente viene eseguita sempre, un'istruzione return eseguita nella clausola finalmente sarà sempre l'ultima eseguita:

Ciò significa che quando provi a tornare, il finallyblocco viene chiamato, restituendo il suo valore, piuttosto che quello che avresti avuto.


4
perché il 5 non viene stampato nel secondo esempio? questo non è ancora ben spiegato credo. quello di ritorno ha una buona risposta, ma perché non il 5 nel secondo esempio di stampa
Joran Beasley,

5
oh, penso di aver capito che il ritorno nel tentativo iniziale lo fa saltare immediatamente verso l'esterno finalmente
Joran Beasley,

2
Esatto, perché i finallyblocchi vengono eseguiti sempre .
Gareth Latty

2
Nella demo due, perché esegue finalmente il nidificato, esplode verso l'esterno e infine torna nel nidificato per finire il ritorno invece di restituire semplicemente Nessuno dall'esterno?
Kyle Owens

1
Perché quando l' returnistruzione viene chiamata, Python verifica eventuali finallyclausole aperte che devono essere eseguite (vedere la citazione sopra).
Gareth Latty

7

L'ordine di esecuzione è:

  1. try block all completa normalmente -> finalmente block -> la funzione termina
  2. provare a eseguire il blocco ed entrare nell'eccezione A -> finalmente blocco -> la funzione termina
  3. prova blocco crea un valore di ritorno e chiama return -> finalmente blocca -> valore di ritorno popup -> la funzione termina

Quindi, qualsiasi ritorno nel blocco finalmente terminerà i passaggi in anticipo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.