subclase de python acceso a la variable de clase del padre

Me sorprendió saber que una variable de clase de una subclase no puede acceder a una variable de clase del padre sin indicar específicamente el nombre de clase del padre:

>>> class A(object): ... x = 0 ... >>> class B(A): ... y = x+1 ... Traceback (most recent call last): File "", line 1, in  File "", line 2, in B NameError: name 'x' is not defined >>> class B(A): ... y = Ax + 1 ... >>> Bx 0 >>> By 1 

¿Por qué es que al definir Por tengo que referirme a Ax y no solo a x? Esto es contrario a mi intuición de las variables de instancia, y ya que puedo referirme a Bx después de que se haya definido B

En Python, el cuerpo de una clase se ejecuta en su propio espacio de nombres antes de que se cree la clase (después de lo cual, los miembros de ese espacio de nombres se convierten en miembros de la clase). Entonces, cuando el intérprete alcanza y = x + 1, la clase B aún no existe en ese punto y, por lo tanto, no tiene padre.

Para obtener más detalles, consulte http://docs.python.org/reference/compound_stmts.html#class-definitions

Las reglas de scope de Python para los nombres de barras son muy sencillas y directas: el espacio de nombres local primero, luego (si corresponde) las funciones externas en las que el actual está nested, luego los globales, finalmente incorporados. Eso es todo lo que siempre ocurre cuando se busca un nombre de barra, y no es necesario memorizar ni aplicar reglas complicadas (ni tampoco es necesario que un comstackdor de Python aplique reglas más complicadas).

Cada vez que desee una búsqueda diferente, utilizará un nombre calificado , no un nombre simple . Los nombres calificados son mucho más poderosos porque la búsqueda siempre puede delegarse a los objetos cuyos atributos se pueden solicitar, y esos objetos pueden implementar las reglas de búsqueda que necesiten. En particular, en un método de instancia dentro de una clase, self.x es la forma de pedirle al objeto self que busque el nombre de atributo 'x' – y en esa búsqueda puede delegar en clases, incluida la implementación del concepto de herencia (y herencia múltiple, orden de resolución de métodos, etc.).

El cuerpo de una clase (a diferencia de los cuerpos de los métodos definidos en una clase) se ejecuta como parte de la statement de la class , antes de que se cree el objeto de la clase o su nombre esté vinculado (en particular, antes de que se haya definido cualquiera de las bases) como base, aunque este último detalle nunca puede importar al referirse a nombres de barras, de todos modos! -).

Entonces, en su ejemplo, en la clase B , el nombre de barra x se busca con las reglas universales, ¿es un nombre vinculado localmente? Si no, ¿está vinculado a alguna función externa en la que este ámbito está nested? Si no, ¿está vinculado como global o incorporado? Si no es ninguno de los anteriores, el uso del nombre de barra en cuestión provoca una excepción de error de nombre.

Ya que usted desea una secuencia de búsqueda diferente a la de las reglas de búsqueda de nombres de barras aplicadas universalmente, entonces claramente necesita usar un nombre calificado, no un nombre de barra; y un momento de reflexión mostrará claramente que la “una opción obvia” para que un nombre calificado lo use para su propósito tiene que ser Ax , ya que es allí donde desea que se busque (las bases aún no se han registrado en ninguna parte en ese punto, después de todo … será la metaclase, normalmente de type , la que hará el enlace de las bases como parte de su trabajo cuando sea llamada después de que el cuerpo de la clase haya terminado de ejecutarse! -).

Algunas personas están tan atadas a otras reglas “mágicas” para la búsqueda de nombres de barras que simplemente no pueden soportar este aspecto de Python (originalmente inspirado, creo, por Modula-3, un lenguaje poco conocido que es muy bien considerado por los teóricos). ‘circles 😉 – tener que escribir self.x en un método para especificar que x debe self.x en self lugar de usar las reglas universales de nombres de barras, por ejemplo, hace que esas personas se vuelvan locas.

A mí, me encanta la simplicidad y la universalidad de las reglas de búsqueda de nombres de barras, y me encanta usar nombres calificados en lugar de nombres de barras en cualquier momento que quiera cualquier otra forma de búsqueda … pero no es un secreto del que estoy locamente enamorado. Python (tengo mis propias quejas, p. Ej., global x como una statement siempre hace que mi skin se arrastre, donde preferiría escribir global.x , es decir, tener global como un nombre incorporado para “el módulo que se está ejecutando actualmente” … Me encantan los nombres calificados! -), ¿verdad? -)