variable nonlocal inside python python-3.x scoping

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.