validar utilizar try tipos recent por most last excepción excepciones ejemplos diferentes como catch python syntax-error continue finally

utilizar - ¿Por qué `continue` no está permitido en una cláusula` finally` en Python?



traceback(most recent call last) python (6)

Creo que la razón para esto es bastante simple. La instrucción continue después de la palabra clave finally se ejecuta todo el tiempo. Esa es la naturaleza de la declaración final. Si su código arroja una excepción o no es irrelevante. Finalmente será ejecutado.

Por lo tanto, tu código ...

for i in range(10): print i try: pass finally: continue print i # this (and anything else below the continue) won''t ever be executed!

es equivalente a este código ...

for i in range(10: print i try: pass finally: pass

que es más limpio y terser. Python no permite continuar en un bloque finally porque todos los códigos posteriores al continuar nunca se ejecutarán. (Sparse es mejor que denso)

El siguiente código genera un error de sintaxis:

>>> for i in range(10): ... print i ... try: ... pass ... finally: ... continue ... print i ... File "<stdin>", line 6 SyntaxError: ''continue'' not supported inside ''finally'' clause

¿Por qué no se permite una declaración de continue dentro de una cláusula finally ?

PD: este otro código, por otro lado, no tiene problemas:

>>> for i in range(10): ... print i ... try: ... pass ... finally: ... break ... 0

Si es importante, estoy usando Python 2.6.6.


El uso de continuar en una cláusula finally está prohibido porque su interpretación habría sido problemática. ¿Qué harías si se ejecutara la cláusula finally por una excepción?

for i in range(10): print i try: raise RuntimeError finally: continue # if the loop continues, what would happen to the exception? print i

Es posible que tomemos una decisión sobre lo que debería hacer este código, tal vez tragando la excepción; pero un buen diseño del lenguaje sugiere lo contrario. Si el código confunde a los lectores o si hay una manera más clara de expresar la lógica prevista (quizás con try: ... except Exception: pass; continue ), entonces hay alguna ventaja al dejar esto como un SyntaxError .

Curiosamente, puede poner un retorno dentro de una cláusula finally y se tragará todas las excepciones, incluidas KeyboardInterrupt , SystemExit y MemoryError . Probablemente tampoco sea una buena idea ;-)


La posibilidad de obtener una excepción y luego simplemente tragarla porque está utilizando un continue es un argumento fuerte, pero la excepción también se traga cuando utiliza un break o return en return lugar.

Por ejemplo, esto funciona y se traga la excepción:

for i in range(10): print i try: raise Exception finally: break print i # not gonna happen

De nuevo, esto funciona sin ningún error (cuando está en una función) y la excepción también se traga:

for i in range(10): print i try: raise Exception finally: return print i # not gonna happen

Entonces, ¿por qué se permitiría el break y el return en un bloque finally , con o sin posibles errores planteados, pero no continue ?

También puede considerar la combinación de los siguientes factores en el problema:

  • finally siempre se ejecuta;
  • continue "aborta" la iteración actual.

Esto significa que dentro de cada bucle, debido a que finally siempre se ejecutará, siempre tendrás una palabra de continue que básicamente dice "abortar la iteración actual", "abortar la iteración actual", "abortar la iteración actual" ... realmente no hace cualquier sentido. Pero tampoco tiene sentido usar break y return . La iteración actual también se interrumpe con la única diferencia de que ahora termina con una sola iteración.

Entonces la pregunta "¿Por qué no se permite continue en un finally ?" también se puede preguntar como "¿Por qué se permiten las break y el return ?".

Tal vez porque tenía sentido no hacerlo en ese momento? Fue decisión de los desarrolladores y ahora es como es? Claro, también podría ser la pereza del implementador, pero quién sabe, tal vez tenían algo en mente y quizás, en otra versión de Python, tendría más sentido que fuera de otra manera.

La idea es que los ejemplos aquí son simplemente extremos . No solo escribes código así, ¿verdad? Seguramente habrá algo de lógica en el bloque final para decir cuándo break/return/continue , lo que sea, y no solo hacerlo de esa manera. Como tal, en mi humilde opinión, finally debería permitirse escribir un código limpio con el uso de continue por finally si eso es lo que necesito, en lugar de recurrir a un código de solución para esta limitación (es decir, en la filosofía de Python "Todos somos consentir adultos aquí ").


No vi que se mencionara en otra respuesta, pero creo que lo que podría querer en este caso es try..else :

for i in range(10): print i try: #pass <= I commented this out! do_something_that_might_fail(i) except SomeException: pass else: continue print i

El bloque else solo se ejecuta si no hubo ninguna excepción. Entonces, ¿qué significa esto?

  1. Nosotros print i
  2. Tratamos de do_something_that_might_fail(i)
  3. Si arroja SomeException , SomeException e SomeException nuevo
  4. De lo contrario, continue (y nunca se imprime)

Python Language Reference prohíbe el uso de continue en una cláusula finally . No estoy del todo seguro de por qué. Tal vez porque continue dentro de la cláusula try asegura que finally se ejecuta, y decidir qué continue debería hacer dentro de la cláusula finally es algo ambiguo.

Editar: El comentario de @Mike Christensen a la pregunta señala un hilo en el que los desarrolladores principales de Python debaten la ambigüedad de esta construcción. Además, en más de nueve años de uso de Python, nunca quise hacer esto, por lo que es probablemente una situación relativamente poco común en la que los desarrolladores no tienen ganas de pasar mucho tiempo.