2012-06-22 13 views
53

Questo è un codice che si comporta in modo particolare. Questa è una versione semplificata del comportamento che ho scritto. Questo dimostrerà ancora il comportamento strano e ho avuto alcune domande specifiche sul perché questo si sta verificando.Weird Try-Except-Else-Finally comportamento con dichiarazioni Return

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 

if __name__ == "__main__": 
    print "*** DEMO ONE ***" 
    print demo1() 
    print "****************" 
    print 
    print "*** DEMO TWO ***" 
    print demo2() 
    print "****************" 

Quando si esegue questo script, verrà stampata:

*** DEMO ONE *** 
3 
**************** 

*** DEMO TWO *** 
6 
3 
**************** 

Perché demo uno tornando 3 invece di 1? Perché la demo due stampa 6 invece di stampare 6 con 4 o 5?

Grazie per il vostro aiuto.

risposta

80

Perché le dichiarazioni finally sono garantito da eseguire (beh, presumendo interruzione di corrente o qualsiasi cosa al di fuori del controllo di Python). Ciò significa che prima che la funzione possa tornare, deve eseguire il blocco finally, che restituisce un valore diverso.

Il Python docs Stato:

Quando un ritorno, rompersi o istruzione continue viene eseguita nella suite try di un'istruzione try ... finally, viene eseguita anche la clausola finally 'sulla via d'uscita.' Una dichiarazione continua è illegale nella clausola finally. (La ragione è un problema con l'attuale implementazione - questa restrizione potrebbe essere revocata in futuro).

Ciò significa che quando si tenta di restituire, il blocco finally si chiama, restituendo il suo valore, piuttosto che quello che si avrebbe avuto.

+1

perché la stampa 5 non è nel secondo esempio? questo non è ancora ben spiegato, penso. il ritorno è ben risposto, ma perché il 5 nel secondo esempio non stampa –

+4

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

+2

Esattamente, perché "finalmente" blocca ** sempre ** correre. –

1

L'ordine di esecuzione è: blocco

  1. prova tutto completato normalmente -> finally -> funzione termina
  2. blocco try conduzione e entrare in eccezione A -> finally -> funzione termina
  3. try block effettua un valore di ritorno e chiama return -> finally block -> popup restituisce valore -> function termina

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

+0

È possibile utilizzare un formato elenco per la risposta. – gsamaras