2011-02-08 11 views
7

Esperamos que este sea lo suficientemente claro:Python: Obtener valores de la clase base de la clase derivada

class myParent(): 
    def __init__(self): 
     self.parentNumber = 5 

class Child(myParent): 
    def __init__(self): 
     self.childNumber = 4 

    def multiplyNumbers(self): 
     print myParent.parentNumber * self.childNumber 

p = Child() 
p.multiplyNumbers() 

Deseo establecer el parentNumber de forma individual, y luego llegar a ese número a través de la clase de niños, y en este caso usarlo para algunos multiplicación.

Soy nuevo en el área de programación orientada a objetos así que cualquier sugerencia general sobre la herencia también es bienvenida.

Más información: Estoy diseñando una solución de gestión de proyectos para proyectos basados ​​en efectos visuales, y estoy jugando con las clases y herencia para ver cómo me pueden ayudar a los más.

Ahora mismo, tengo la clase superior, Project y una clase derivada, Shot. Shot tiene una variable self.length con la duración de la toma específica. También tiene un método getLengthInSeconds() que usa self.length junto con Project.fps para determinar la longitud en segundos. Project tiene un método setFps() en el que el fps se establece después de crear una instancia de la clase.

Estoy acostumbrado a que las variables tengan un prefijo propio. y no han experimentado mucho con clases usando las variables más "globales" sin auto. . Si hago que todo sea global, no consigo., Puedo usar Project.fps sin problemas, pero recibo una advertencia de "mala práctica de programación" en mi cuello de cisne. ¿Tal vez hay una manera mejor y más ordenada?

Editar:

Después de un poco de lectura, super() parece un poco peligroso, y un poco más de lo que necesito que pienso. Principalmente tengo clases de herencia única y ni siquiera estoy seguro de cómo hacer uso de las jerarquías de diamantes. ¿Existe alguna forma más segura de acceder a las variables y métodos de superclase que no incluye a super()?

Editar:

De acuerdo, a ver si esto tiene sentido o si estoy pensando de la manera equivocada.

Estoy buscando clases y herencia como grupos y niños. Un niño sabe que es padre y todos sus valores. Un niño con otro padre sabe que los valores de los padres. Lo que intento lograr es hacer que todas las tomas creadas sean parte de un proyecto. Y en este momento, estoy creando instancias de Shot() desde la clase Project(), agregando las instancias a una lista de disparos que luego se mantiene dentro de la instancia de Project().

es decir

class myParent(object): 
    def __init__(self): 
     self.parent_id = '' 
     self.children = [] 

    def createChild(self, name): 
     self.children.append(myChild(name)) 

    def getChildren(self): 
     return self.children 

    def setParentId(self, id): 
     self.parentId = id 

class myChild(myParent): 
    def __init__(self, id): 
     super(myChild, self).__init__() 
     self.id = id 

    def getParentId(self): 
     return self.parent_id 

p = myParent() 
p.setParentId('parent01') 
p.createChild('child01') 
print p.getChildren()[0].getParentId() 

puedo especie de ver las mis-pasos en la lógica aquí, pero no hay forma real a su alrededor .. Parece que cada niño reciba una nueva instancia de la matriz de esta manera, en donde parent_id siempre es una cadena vacía.

+0

es necesario llamar al constructor de la superclase. –

Respuesta

5
class myParent(object): 
    def __init__(self): 
     self.parentNumber = 5 

class Child(myParent): 
    def __init__(self): 
     myParent.__init__(self) 
     self.childNumber = 4 

    def multiplyNumbers(self): 
     print self.parentNumber * self.childNumber 

p = Child() 
p.multiplyNumbers()

por lo general Usted puede manejar muy bien sin super cuando no tiene otros casos fronterizos herencia múltiple o , aunque si la clase base cambia, deberá recordar cambiar el nombre de la clase principal de init (y cualquier otro método que haga referencia explícitamente a myParent).

Si los parámetros de su padre son __init__, debe pasarlos del __init__ del niño.

class myParent(object): 
    def __init__(self, customParam): 
     self.parentNumber = 5 
     self.customParam = customParam 

class Child(myParent): 
    def __init__(self, customParam): 
     myParent.__init__(self, customParam) 
     self.childNumber = 4

Si no le gusta la repetición de customParam en todas las clases hijas, no hay un patrón alternativo OO llamada construcción de dos fases, que funciona así:

class myParent(object): 
    def customInit(self, customParam): 
     self.parentNumber = 5 
     self.customParam = customParam 

class Child(myParent): 
    def __init__(self, customParam): 
     self.childNumber = 4 

p = Child() 
p.customInit(10) 
p.multiplyNumbers() 

En este patrón, que no es necesario para repetir cualquiera de los parámetros de los padres, o incluso llamar al padre __init__ en el niño, pero la desventaja es que tendrá que recordar llamar siempre al constructor secundario al crear objetos, o su objeto se dejará parcialmente sin inicializar.

ACTUALIZACIÓN (Para contestar la pregunta actualizada):

Usted parece ser la mezcla de dos conceptos no relacionados de la paternidad aquí. La herencia se trata de la jerarquía de tipos, y parece que busca una jerarquía de propiedad (is-a versus has-a).

que sería la estructura de su código actualizado de esta manera:

class myParent(object): 
    def __init__(self, parentId): 
     self.id = parentId 
     self.children = [] 

    def createChild(self, name): 
     self.children.append(myChild(name, self)) 

    def getChildren(self): 
     return self.children 

class myChild(object): 
    def __init__(self, childId, parent): 
     self.id = childId 
     self.parent = parent 

    def getParentId(self): 
     return self.parent.id 

p = myParent('parent01') 
p.createChild('child01') 
print p.getChildren()[0].getParentId()
+0

¡Gracias por su respuesta! ¿Te importaría echarle un vistazo a la pregunta actualizada? –

+0

@Marcus: actualizó la respuesta – shang

+0

Sí, eso tiene mucho más sentido. ¡Gracias! –

5

Solo necesita indicar Child para ejecutar la inicialización desde myParent. Después de eso, la instancia actual (self) tiene todos los atributos de instancia que tendría una instancia de myParent ("is a"), por lo que puede usar self.parentNumber. Para ello, ponga super(Child, self).__init__() en Child.__init__ (idealmente, en la primera línea) - myParent.__init__(self) funcionaría, pero puede ser incorrecto (de manera sutil) cuando la clase base cambia o en caso de herencia múltiple. Puede soltar todos los argumentos al super si está utilizando Python 3.

También tenga en cuenta que

class C(object): 
    x = ... 

es muy diferente de

class C(object): 
    def __init__(self): 
     self.x = ... 

El primero crea una variable de clase, que es compartida por todas las instancias de C. Este último crea una variable de instancia, cada instancia de C tiene su propia cuenta. (Del mismo modo, las variables globales no están vinculados a instancias - pero supongo que hablabas de lo anterior?)

+1

+1 .. y debería ser 'self.parentNumber' en' multiplyNumbers'. – sdolan

+0

@sdolan: Sí, incluido. – delnan

+0

Solo el tipo de información que estaba buscando. Voy a tratar de salir. –

Cuestiones relacionadas