Python try finally block devuelve [duplicar]


Esta pregunta ya tiene una respuesta aquí:

Hay un código interesante a continuación:

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

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

func1()
func2()

Podría por favor alguien explicar, qué resultados devolverán estas dos funciones y explicar POR QUÉ, es decir, describir el orden de la ejecución

Author: skybobbi, 2013-11-06

4 answers

De la documentación de Python

Siempre se ejecuta una cláusula finally antes de salir de la sentencia try, se haya producido o no una excepción. Cuando se ha producido una excepción en la cláusula try y no ha sido manejada por una cláusula except (o ha ocurrido en una cláusula except or else), se vuelve a plantear después de que se haya ejecutado la cláusula finally. La cláusula finally también se ejecuta "en la salida" cuando cualquier otra cláusula de la instrucción try se deja a través de un break, continue or return statement . Un ejemplo más complicado (que tiene cláusulas except y finally en la misma instrucción try funciona como en Python 2.5):

Así que una vez que el bloque try/except se deja usando return, que establecería el valor de retorno a given - finalmente los bloques siempre se ejecutarán, y deberían usarse para liberar recursos, etc. mientras se usa allí otro retorno-sobrescribe el original.

En tu caso particular, func1() devuelve 2 y func2() return 3, ya que estos son valores devueltos en los bloques finally.

 77
Author: lejlot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-13 16:20:47

Siempre irá al bloque finally, por lo que ignorará los retornos en el try en except. Si tuviera un retorno por encima del try and except, devolvería ese valor.

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
 23
Author: user1408786,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-06 06:49:37

Poner print declaraciones de antemano realmente, realmente ayuda:

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()

Esto devuelve:

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

Notarás que python siempre devuelve lo último que se devuelve, independientemente de que el código "haya alcanzado" return 1 en ambas funciones.

Un bloque finally es siempre se ejecuta, por lo que lo último que se devuelve en la función es lo que se devuelve en el bloque finally. En func1, eso es 2. En func2, eso es 3.

 7
Author: TerryA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-06 06:48:56

func1() devuelve 2. func2() devuelve 3.

finally el bloque se ejecuta finalmente independientemente o excepción.

Puede ver el orden de ejecución usando debugger. Por ejemplo, vea un screencast.

 1
Author: falsetru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-06 06:47:08