2012-01-13 24 views
23

Soy una persona de Java que acaba de empezar a aprender Python. Tome este ejemplo:Herencia de atributos en python usando __init__

class Person(): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 

class Teenager(Person): 
    def __init__(self, name, phone, website): 
     self.name=name 
     self.phone=phone 
     self.website=website 

Estoy seguro de que hay una gran cantidad de código redundante (sé en Java, hay una gran cantidad de despidos para el bit de código anterior).

¿Qué partes son redundantes con respecto a qué atributos ya se heredan de la clase padre?

Respuesta

29

Al escribir la función __init__ para una clase en python, siempre debe llamar a la función __init__ de su superclase. Podemos usar esto para pasar los atributos relevantes directamente a la superclase, por lo que el código se vería así:

class Person(object): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 
class Teenager(Person): 
    def __init__(self, name, phone, website): 
     Person.__init__(self, name, phone) 
     self.website=website 

Como otros han señalado, puede reemplazar la línea

Person.__init__(self, name, phone) 

con

super(Teenager, self).__init__(name, phone) 

y el código va a hacer lo mismo. Esto es porque en python instance.method(args) es solo una abreviatura de Class.method(instance, args). Si desea utilizar super, debe asegurarse de especificar object como la clase base para Person como lo he hecho en mi código.

El python documentation tiene más información sobre cómo usar la palabra clave super. Lo importante en este caso es que se le dice a Python para buscar el método __init__ en una superclase de self que no es Teenager

+2

Tenga en cuenta que si está utilizando Python 2.x, debe enumerar explícitamente 'object' como una clase base de' Person' para poder usar 'super()'. De lo contrario, debe usar la forma 'Persona .__ init__'. – chepner

+0

@chepner ¿puede proporcionar una referencia para eso? No puedo encontrar uno – murgatroid99

+0

http://docs.python.org/library/functions.html#super indica que super() solo se admite en las clases de estilo nuevo, que en Python 2.x son las que heredan de 'object' – chepner

5

atributos en Python no se heredan cuando se definen en el constructor y el padre constructor de la clase no se llama , a menos que usted hace todo de forma manual:

class Person(): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 
class Teenager(Person): 
    def_init_(self, name, phone, website): 
     Person.__init__(self, name, phone) # Call parent class constructor. 
     self.website=website 

Más sobre ella aquí: http://docs.python.org/tutorial/classes.html#inheritance

1

__init__, a diferencia de un constructor de java, no se llama automáticamente para cada clase en la jerarquía de herencia - que necesita t o hazlo tú mismo.

Además, todas las jerarquías de objetos debe erradicarse en object (excepto en casos especiales).

El código debería leer:

class Person(object): 
    def __init__(self, name, phone): 
     self.name = name 
     self.phone = phone 
class Teenager(Person): 
    def_init_(self, name, phone, website): 
     super(Teenager, self).__init__(name, phone) 
     self.website=website 

super crea un delegado para su segundo argumento (self), que se llame a la función siguiente en la lista de funciones que llamar para cada nombre (la "resolución de la orden Método "). Esto no es lo mismo que llamar al método de superclase, como ocurre en Java.

También puede escribir super(type(self), self).__init__(name, phone), pero si hereda más lejos de esta clase, type(self) puede no ser , y podría tener una recursión infinita. Esta es una consecuencia práctica del hecho de que está trabajando con un objeto delegado con una diferencia MRO, en lugar de llamar directamente a un constructor de superclase.

11

manera un poco más limpio que me gusta hacer esto:

class Teenager(Person): 
     def __init__(self, *args, **kwargs): 
      self.website=kwargs.pop('website') 
      super(Teenager, self).__init__(*args, **kwargs) 

no hace mucha diferencia en este caso, pero cuando tiene una __init__ con una tonelada de argumentos, que hace la vida más fácil.

+0

Upvoted para el uso de * args y ** kwargs (... eficiente en el caso de numerosos argumentos). –

Cuestiones relacionadas