2012-02-13 11 views
5
In [5]: class a(object): 
    ...:  def __init__(self): 
    ...:   print "In class a" 
    ...:   self.a = 1 
    ...:   
In [6]: class b(object): 
    ...:  def __init__(self): 
    ...:   print "In class b" 
    ...:   self.b = 2 
    ...:   
    ...:   

In [7]: class c(b, a): 
    ...:  pass 
    ...: 
In [8]: c.mro() 
Out[8]: 
[<class '__main__.c'>, 
<class '__main__.b'>, 
<class '__main__.a'>, 
<type 'object'>] 

In [9]: obj = c() 
In class b 

In [10]: obj.__dict__ 
Out[10]: {'b': 2} 

El valor predeterminado __init__ método de la clase c se llama en obj creación, que llama internamente al __init__ de b única clase.Comportamiento de Mutlple herencia en pitón

Según mi entender, si heredo de 2 clases, mi objeto de clase derivado debería tener variables de ambas clases (a menos que sean privadas para esas clases).

Mi pregunta: ¿Me equivoco al esperar que mi objeto derivado contenga variables de ambas clases? Si es así, ¿por qué? ¿No se debe llamar también al __init__ de la clase a? ¿Qué hubiera pasado en un lenguaje como C++?

+0

La respuesta de jcollado es correcta. Ver [esta respuesta] (http://stackoverflow.com/q/607186) para más detalles sobre cómo funciona 'super'. – perelman

Respuesta

8

En python, los métodos de inicialización de las clases superiores no se llaman por defecto. Para hacer eso, usted tiene que llamar explícitamente a ellos utilizando super de la siguiente manera:

class a(object): 
    def __init__(self): 
     super(a, self).__init__() 
     print "In class a" 
     self.a = 1 

class b(object): 
    def __init__(self): 
     super(b, self).__init__() 
     print "In class b" 
     self.b = 2 

class c(b, a): 
    pass 

obj = c() 

Ejemplo de salida.

en la clase A
en la clase B

Editar: En cuanto a por qué esto funciona de esta manera, yo diría que es una decisión de diseño basado en The Zen of of Python:

Explícito es mejor que implícito.

+0

por qué el método 'super (b, self) .__ init __()' llamar '__init__' de a, a no es una superclase de b, ¿significa que la sintaxis llama al siguiente objeto en la secuencia mro? – avasal

+0

@avasal, sí, la llamada 'super' encontrará el siguiente método disponible en la secuencia de mro. Tenga en cuenta que el código proporcionado solo funciona porque 'objeto .__ init__' existe y se llama sin argumentos: si el' __init__' en las clases tomó un argumento, o si desea propocionar otro método, entonces puede necesitar una clase de stub intermedio para terminar la cadena de llamadas 'super'. Véase también http://rhettinger.wordpress.com/2011/05/26/super-considered-super/ – Duncan