una otra llamar listas instanciar ejemplo dentro crear con como clases clase python subclass class-variables

otra - python ejemplo clases



acceso de la subclase python a la variable de clase de padre (2)

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 "<stdin>", line 1, in <module> File "<stdin>", line 2, in B NameError: name ''x'' is not defined >>> class B(A): ... y = A.x + 1 ... >>> B.x 0 >>> B.y 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 a partir de variables de instancia, y dado que puedo referirme a Bx después de que se define 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 los 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 alcance de Python para nombres desnudos son muy simples y sencillas: primero el espacio de nombres local, luego (si hay) funciones externas en las que se anida el actual, luego globales, finalmente integradas. Eso es todo lo que sucede cuando se busca un nombre simple, y no hay necesidad de memorizar o aplicar ninguna regla complicada (ni existe la necesidad de que un compilador de Python aplique reglas más complicadas).

Cada vez que desee una búsqueda diferente, usará un nombre calificado , no un nombre simple . Los nombres calificados son mucho más potentes porque la búsqueda siempre se puede delegar 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 manera de pedirle al objeto que busque el nombre del 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 (en oposición a los cuerpos de los métodos definidos en una clase) se ejecuta como parte de la declaración de class , antes de que se cree el objeto de la clase o su nombre esté vinculado (en particular, antes de que se haya definido alguna de las bases) como bases, aunque este último detalle nunca puede importar cuando se refiere a nombres desnudos, de todos modos! -).

Entonces, en su ejemplo, en la clase B , barename x se busca con las reglas universales. ¿Se trata de un nombre vinculado localmente? Si no, ¿está vinculado a alguna función externa en la que este ámbito está anidado? Si no, ¿está vinculado como global o incorporado? Si ninguno de los anteriores, utilizando el nombre en concreto en cuestión, por supuesto, causa una excepción de error de nombre.

Dado que desea una secuencia de búsqueda diferente de las reglas de búsqueda barename que se aplican universalmente, entonces claramente necesita usar un nombre calificado, no un nombre simple; y un momento de reflexión mostrará claramente que la "única opción obvia" para un nombre calificado para usar para su propósito debe ser Ax - ya que es donde usted quiere que se busque (las bases no se han registrado en ningún lado aún en ese punto, después de todo ... será la metaclase, normalmente el type , que hará las bases vinculantes como parte de su trabajo cuando se llame después de que el cuerpo de la clase termine de ejecutar! -).

Algunas personas están tan apegadas a otras reglas "mágicas" para la búsqueda de nombres desnudos que simplemente no pueden soportar este aspecto de Python (originalmente inspirado, creo, por Modula-3, un lenguaje poco conocido que está muy bien considerado en teóricos ''círculos ;-) - tener que escribir self.x en un método para especificar que x debe buscarse a self lugar de usar las reglas universales barename, por ejemplo, impulsa a esas personas a la rudeza.

A mí, me encanta la simplicidad y la universalidad de las reglas de búsqueda barename, y me encanta usar nombres calificados en lugar de nombres desnudos cada vez que quiero cualquier otra forma de búsqueda ... pero luego, no es ningún secreto que estoy locamente enamorado de Python (tengo mis propios refunfuños, por ejemplo, global x como afirmación, siempre me pone los pelos de global.x , donde preferiría escribir global.x , es decir, tener global ser un nombre incorporado para "el módulo que se está ejecutando actualmente" ... Me encantan los nombres calificados! -), ¿verdad? -)