2009-07-16 9 views
14

Esto es lo que estoy tratando de hacer en Python:Python herencia y llamando a los padres constructor de la clase

class BaseClass: 
    def __init__(self): 
     print 'The base class constructor ran!' 
     self.__test = 42 

class ChildClass(BaseClass): 

    def __init__(self): 
     print 'The child class constructor ran!' 
     BaseClass.__init__(self) 

    def doSomething(self): 
     print 'Test is: ', self.__test 


test = ChildClass() 
test.doSomething() 

que se traduce en:

AttributeError: ChildClass instance has no attribute '_ChildClass__test' 

Lo que da? ¿Por qué esto no funciona como espero?

+0

call baseclass .-- init-- antes de hacer cualquier otra cosa para referencia futura, –

Respuesta

20

De la documentación de Python:

nombre privada mangling: Cuando un identificador que se produce textualmente en una definición de clase comienza con dos o más subrayar caracteres y no termina en dos o más guiones, se considera un nombre privado de esa clase. Los nombres privados son transformados a un formato más largo antes de que se genere el código para ellos. La transformación inserta el nombre de la clase delante del nombre, con guiones bajos eliminados, y un solo guión bajo insertado delante del nombre de la clase. Por ejemplo, el identificador __spam que se encuentra en una clase denominada Ham se transformará en _Ham__spam. Esta transformación es independiente del contexto sintáctico en el que se utiliza el identificador. Si el nombre transformado es extremadamente largo (más de 255 caracteres), puede producirse un truncamiento definido por la implementación. Si el nombre de la clase consiste únicamente en guiones bajos, no se realiza ninguna transformación.

Así que su atributo no se nombra __test pero _BaseClass__test.

Sin embargo, no debe depender de eso, use self._test y la mayoría de los desarrolladores de Python sabrán que el atributo es una parte interna de la clase, no la interfaz pública.

+1

Ah ... entonces, ¿hay una manera "correcta" o "pitónica" de acceder a esos miembros privados si necesito extender una clase? eso es usar esa sintaxis? –

+0

@Keith: es una pregunta más OOP que python. Al acceder a un miembro privado de una superclase, está rompiendo la encapsulación y creando una fuerte dependencia entre las clases. Superclass ya no puede cambiar su funcionamiento interno, incluso si la interfaz pública se mantiene igual.En resumen: no hagas eso :) –

+0

Desafortunadamente, eso significa que puedo volver a escribir la biblioteca python smtpd, o copiar/pegar toda la biblioteca smtpd en un nuevo archivo. Realmente no quiero hacer ninguna de esas cosas, pero necesito acceso a las variables privadas de las bibliotecas smtpd ... –

3

Las variables de doble subrayado se pueden considerar "privadas". Están destrozados con el nombre de la clase, entre otros, para proteger a múltiples clases de base de anular los miembros de cada uno.

Utilice un guión bajo único si desea que otros desarrolladores consideren privado su atributo.

5

Puede utilizar las instalaciones de introspección de Python para obtener la información que está buscando. Una sencilla dir (prueba) le dará

['_BaseClass__test', '__doc__', '__init__', '__module__', 'doSomething'] 

la Nota de la _BaseClass__test '. Eso es lo que estás buscando.

Compruebe this para obtener más información.

+0

Esa es la mitad de la historia, como se señaló anteriormente, pero dir (unknown_thing) siempre es un buen paso. – taynaron

Cuestiones relacionadas