¿Por qué 'continue `no está permitido en una cláusula` finally' en Python?
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 instrucción continue
dentro de una cláusula finally
?
P.d. Este otro código por otro lado no tiene problemas:
>>> for i in range(10):
... print i
... try:
... pass
... finally:
... break
...
0
Si importa, estoy usando Python 2.6.6.
6 answers
El uso de continue en una cláusula final está prohibido porque su interpretación habría sido problemática. ¿Qué harías si la cláusula final fuera ejecutada debido a 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 este código debería hacer, tal vez tragándonos la excepción; pero el buen diseño del lenguaje sugiere lo contrario. Si el código confunde a los lectores o si hay una forma más clara de expresar la lógica deseada (tal vez con try: ... except Exception: pass; continue
), entonces hay alguna ventaja de dejar esto como un SyntaxError .
Curiosamente, puede poner un return dentro de una cláusula finally-y se tragará todas las excepciones incluyendo KeyboardInterrupt, SystemExit , y MemoryError. Eso probablemente no es una buena idea tampoco ; -)
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
2011-11-29 19:37:56
La Referencia del Lenguaje Python prohíbe el uso de continue
dentro de una cláusula finally
. No estoy del todo seguro de por qué. Quizás porque continue
dentro de la cláusula try
asegura que la finally
se ejecuta, y decidir qué debe hacer continue
dentro de la cláusula finally
es algo ambiguo.
Edit: el comentario de @Mike Christensen a la pregunta señala un hilo donde la ambigüedad de esta construcción es discutida por los desarrolladores del núcleo de Python. Además, en más de nueve años de uso de Python, Nunca he querido hacer esto, así que probablemente sea una situación relativamente poco común en la que los desarrolladores no tengan ganas de pasar mucho tiempo.
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
2011-11-28 21:17:57
Creo que la razón de esto es en realidad bastante simple. La instrucción continue después de la palabra clave finally se ejecuta cada vez. Esa es la naturaleza de la declaración final. Si tu código lanza o no una excepción es irrelevante. Finalmente será ejecutado.
Por lo tanto, su 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 conciso. Python no permite continuar en un bloque finally porque todo el código después de continuar nunca será ejecutar. (Disperso es mejor que denso.)
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
2011-11-29 02:02:21
No lo vi mencionado 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 excepción. Lo que esto significa es:
- Nosotros
print i
- Nosotros
try
ado_something_that_might_fail(i)
- Si se lanza
SomeException
, caer a través yprint i
de nuevo - De lo contrario, nosotros
continue
(yi
nunca se imprime)
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
2017-05-23 12:23:06
La posibilidad de obtener una excepción planteada y luego simplemente tragada porque está utilizando un continue
es un argumento fuerte, pero la excepción también se ingiere cuando se utiliza un break
o return
en su lugar.
Por ejemplo, esto funciona y la excepción es tragada:
for i in range(10):
print i
try:
raise Exception
finally:
break
print i # not gonna happen
Esto de nuevo funciona sin 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é break
y return
ser permitido en un finally
bloque, con o sin posible planteadas errores, pero continue
no?
También podría considerar la combinación de los siguientes factores en el asunto:{[26]]}
-
finally
siempre se ejecuta; -
continue
"aborta" la iteración actual.
Esto significará que dentro de cada bucle, debido a la finally
siempre ejecutándose, siempre tendrá una continue
bruja básicamente
dice que "abortar iteración actual", "abortar iteración actual", "abortar iteración actual" ... la bruja no tiene ningún sentido. Pero no tiene sentido usar break
y return
. La iteración actual también se aborta con la única diferencia
que ahora terminas con una sola iteración.
Entonces la pregunta "¿Por qué continue
no está permitido en un finally
?"también se puede preguntar como" ¿Por qué se permite break
y return
?".
Tal vez porque tenía sentido no hacerlo en ese momento? Fue la 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 tal vez, en otra versión de Python, haría más ¿sentido de tenerlo de otra manera?
La idea es que los ejemplos aquí son simplemente extremos. No escribes código así, ¿verdad? Hay algunos
lógica en el bloque finally
para decir cuándo a break/return/continue
, lo que sea, y no solo tener que romo así. Como tal, IMHO continue
dentro de un finally
debería ser permitido porque apreciaría escribir un código limpio con el uso de continue
en finally
si eso es lo que necesito, en lugar de recurrir a una solución de código para esta limitación (es decir, en la filosofía de Python "Todos somos adultos que consentimos aquí").
Una declaración continue era ilegal en la cláusula finally debido a un problema con la implementación. En Python 3.8 esta restricción fue levantada.
El error fue issue32489 - Allow 'continue' in 'finally' clause.
La solicitud de extracción para la corrección: https://github.com/serhiy-storchaka/cpython/pull/2
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
2018-04-20 05:32:23