2011-03-28 9 views
9

Estoy tratando de realizar algún análisis de alcance en el código fuente de Python 3 y estoy atascado con cómo funciona la instrucción de declaración no local dentro de una definición de clase.instrucción no local de Python en una definición de clase

Según tengo entendido, la definición de clase ejecuta su cuerpo dentro de un nuevo espacio de nombres (llámelo dict) y vincula el nombre de clase al resultado del tipo (nombre, bases, dict). La x no local debe funcionar siempre que se refiera a una variable enlazada en algún lugar dentro del alcance no local adjunto.

De esta espero que el siguiente código para compilar y ejecutar:

class A: 
    v = 1 
    class B: 
     nonlocal v 
     v = 2 

pero esta falla con

SyntaxError: no binding for nonlocal 'v' found 

mientras que el siguiente código funciona perfectamente

def A(): 
    v = 1 
    class B: 
     nonlocal v 
     v = 2 

¿Puede alguien explicar la diferencia aquí entre el cierre de la definición de la función y la definición de la clase?

+0

Más investigación: en la última muestra de código, locals() en A es {v: 1}, mientras que dentro B es {v: 2, ''__module__'': '' __main__'', ''__locals__'': {...}} – Andyrooger

Respuesta

10

El ámbito léxico se aplica solo a espacios de nombres de funciones; de lo contrario, los métodos definidos dentro de una clase podrían "ver" los atributos de nivel de clase (que por diseño se deben acceder como atributos de self dentro del método).

Las mismas limitaciones que provocan que las variables de nivel de clase sean omitidas por las referencias de los métodos también evitan que la palabra clave nonlocal haga su magia. (global funciona, ya que eso no depende de la maquinaria de alcance léxico)

+0

Gracias, esto tiene sentido. Había asumido que había una forma muy básica de pila que funcionaría igual para cada nivel. Al notar los documentos del módulo symtable cambié de opinión, pero no entendí realmente lo que estaba sucediendo o por qué hasta su respuesta. – Andyrooger

4

Python maneja las definiciones de clases y funciones de manera diferente. Por ejemplo, su A.v no es una variable de A sino un atributo de ella. El espacio de nombres creado por una clase no es, por lo tanto, un alcance. No me sorprende que nonlocal no funcione ya que estás tratando de usarlo.

+0

Gracias por la respuesta. Entonces, el alcance de la función se crea cuando se ejecuta en lugar de cuando se define. Como el cuerpo de la definición de clase es, supongo, ejecutado inmediatamente en un espacio de nombres diferente, ¿no crea esto un alcance solo para la duración de esta ejecución? - Me pregunto si esto sucede por la misma razón que una clase interna no puede acceder a los atributos de una clase externa ... – Andyrooger

+0

Crea un alcance temporal, pero es un * tipo * de alcance diferente. El compilador usa reglas diferentes para decidir qué atributos son visibles (tanto para referencia desde ámbitos internos como para escribir en ámbitos externos). – ncoghlan

Cuestiones relacionadas