2011-12-23 22 views
18

Al leer el código de OpenStack y me encontré con esto.¿Qué hace el método __init __() del objeto en python?

Una clase llamada 'Servicio' hereda el 'objeto' de la clase base, y luego en el método __init__() del Servicio, se llama al objeto __init__. El código relacionado es el siguiente:

la definición de clase:

class Service(object): 

y definición del método init del servicio:

def __init__(self, host, binary, topic, manager, report_interval=None, 
      periodic_interval=None, *args, **kwargs): 

y una llamada a super (el 'objeto' aquí) en el inicio del servicio :

super(Service, self).__init__(*args, **kwargs) 

no entiendo la última llamada, object.__init__() lo que lo hace real ¿Lo hago? ¿Alguien puede ayudar?

Respuesta

14

La respuesta corta es que objeto .__ init __() método no hace nada más que comprobar que no hay argumentos han sido aprobadas en. Ver the source para más detalles.

Cuando llama en una instancia de servicio , la llamada super() delegará a oponerse .__ init __() y no pasará nada.

Sin embargo, cuando se invoca una instancia de una subclase del servicio , las cosas se vuelven más interesantes. La llamada super() puede delegar en alguna clase que no sea objeto, una clase que es un elemento primario de la instancia pero no un elemento primario del servicio . Para obtener detalles sobre cómo funciona esto y por qué es útil, consulte la publicación del blog Python's Super Considered Super.

El siguiente ejemplo (un tanto artificial) muestra cómo una subclase de Servicio puede hacer que el súper llamada en Servicio para ser dirigido a otra clase llamada color:

class Service(object): 
    def __init__(self, host, binary, topic, manager, report_interval=None, 
      periodic_interval=None, *args, **kwargs): 
     print 'Initializing Service' 
     super(Service, self).__init__(*args, **kwargs) 

class Color(object): 
    def __init__(self, color='red', **kwargs): 
     print 'Initializing Color' 
     self.color = color 
     super(Color, self).__init__(**kwargs) 

class ColoredService(Service, Color): 
    def __init__(self, *args, **kwds): 
     print 'Initializing Colored Service' 
     super(ColoredService, self).__init__(*args, **kwds) 

c = ColoredService('host', 'bin', 'top', 'mgr', 'ivl', color='blue') 

En el ejemplo, las inicializaciones se producen en el siguiente orden:

  1. Initializing Colored Servicio
  2. Inicializando el servicio
  3. Inicialización de color
  4. inicializar el objeto - no hacer nada excepto comprobación de argumentos
+2

la referencia [Súper Considerado Súper de Python] (http://rhettinger.wordpress.com/2011/05/26/super-considered-super/) ayuda mucho. ¡Gracias! –

+1

El constructor 'ColoredService' permite, p. 'foo = 'bar'' para pasar, pero esto finalmente fallará con' TypeError: object .__ init __() no toma parámetros'. Entonces, ¿qué sentido tiene pasar '* args' y' ** kwargs' en las llamadas 'super' para las clases' Service' y 'Color'? Su ejemplo funcionará igual sin ellos (y será más robusto). – ekhumoro

+0

@ekhumoro Ese comentario debe dirigirse a los escritores de OpenStack. La parte '' * args'' era de su código y los llamantes deben respetar esa firma. Acabo de agregar * Color * y * ColorService * para mostrar cómo el MRO puede encadenar desde * Servicio * a * Color * a * objeto *. –

3

super()no siempre devuelve un proxy para la clase principal. En su lugar, devuelve un proxy para la próxima clase en MRO. En la herencia única no hay diferencia entre MRO y la cadena de herencia. En herencia múltiple, MRO puede dar como resultado una clase en la otra cadena de herencia .

+0

pero no hay herencia múltiple-aquí, ya que el servicio hereda directamente de objeto –

+0

@can .: Pero lo que hereda de 'Servicio'? –

+0

He leído el artículo sobre MRO, y creo que como el Servicio hereda directamente del objeto, el super() no tiene ambigüedad aquí. Whaterver hereda del Servicio no hace la diferencia. –

1

object.__init__() no hace nada en realidad, pero la llamada super() se debe incluir incluso cuando una clase solo tiene object como una superclase.

One big problem with 'super' is that it sounds like it will cause the superclass's copy of the method to be called. This is simply not the case, it causes the next method in the MRO to be called (...) People omit calls to super(...).init if the only superclass is 'object', as, after all, object.init doesn't do anything! However, this is very incorrect. Doing so will cause other classes' init methods to not be called.

http://fuhm.net/super-harmful/

+0

Pero tenga en cuenta que el código de ejemplo del OP fallará si se pasa algo por '* args' y' ** kwargs' (a menos que se ejecute con python 2.5 o anterior). – ekhumoro

+0

pueden ustedes dos explicar sus ideas con más detalles? @ekhumoro –

Cuestiones relacionadas