nonlocal - python global
"Excepto Foo como barra" hace que "barra" se elimine del ámbito (3)
Esta pregunta ya tiene una respuesta aquí:
Dado el siguiente código:
msg = "test"
try:
"a"[1]
except IndexError as msg:
print("Error happened")
print(msg)
¿Alguien puede explicar por qué esto causa la siguiente salida en Python 3?
Error happened
Traceback (most recent call last):
File "test.py", line 6, in <module>
print(msg)
NameError: name ''msg'' is not defined
Los bloques de excepción eliminan la variable capturada al final del bloque, pero no tienen sus propios ámbitos. Entonces la secuencia de eventos va:
1) msg
se establece en alguna cadena en el ámbito local
2) msg
se establece en un objeto IndexError en el mismo ámbito local que 1
3) msg
se elimina del ámbito local cuando finaliza el bloque de Excepción
4) msg
ya no está definido en el ámbito local, por lo que el intento de acceder falla.
Sí, tan pronto como se genera la excepción y se asigna a msg
el nuevo objeto de excepción, el objeto original no tiene más referencias y, por lo tanto, se elimina. El nuevo objeto de excepción también se elimina tan pronto como sale del bloque de except
.
Puede verificarlo anulando el método __del__
del objeto y la excepción asignada a msg
:
class A:
def __del__(self):
print(''object deleted'')
class E(Exception):
def __del__(self):
print(''exception deleted'')
msg = A()
try:
raise E()
except E as msg:
print("Error happened")
Esto produce:
object deleted
Error happened
exception deleted
NameError: name ''msg'' is not defined
msg
en la cláusula de excepción está en el mismo ámbito que msg
en la primera línea.
Pero en Python 3 también tenemos este nuevo comportamiento :
Cuando se ha asignado una excepción utilizando
as target
, se borra al final de la cláusula de excepción. Esto es como si
except E as N: foo
fue traducido a
except E as N: try: foo finally: del N
Esto significa que la excepción debe asignarse a un nombre diferente para poder referirse a ella después de la cláusula de excepción. Las excepciones se eliminan porque con el rastreo adjunto a ellas, forman un ciclo de referencia con el marco de la pila, manteniendo con vida a todos los locales en ese marco hasta que se produzca la próxima recolección de basura.
así, "sobrescribe msg
" en el controlador de excepciones, y al salir del controlador se eliminará la variable para borrar el ciclo de referencia de rastreo.