2010-03-08 14 views
209
class A: 
def __init__(self): 
    print "world" 

class B(A): 
def __init__(self): 
    print "hello" 

B() 
hello 

En todos los otros lenguajes con los que he trabajado, el super constructor se invoca implícitamente. ¿Cómo se puede invocar en Python? Esperaría super(self) pero esto no funciona.¿Cómo invocar al superconstructor?

+0

Posible duplicado de [Constructores principales de llamada en cadena en python] (http://stackoverflow.com/questions/904036/chain-calling-parent-constructors-in-python) –

Respuesta

232

super() devuelve un objeto padre como en las clases de nuevo estilo:

class A(object): 
    def __init__(self): 
     print "world" 

class B(A): 
    def __init__(self): 
     print "hello" 
     super(B, self).__init__() 

B() 
+42

por curiosidad, ¿por qué 'super (B , self) '¿se deben mencionar tanto B como self? ¿No es esto redundante? ¿Ya no debería contener una referencia a B? – Mike

+75

No, porque 'self' podría ser una instancia de' C', un hijo de 'B'. –

+0

¿Qué pasa si 'B (A, AA)'? Veo que 'super (B, self)' devuelve 'A', pero ¿cómo obtienes' AA'? –

47

Con las clases de estilo antiguo Python 2.x sería la siguiente:

class A: 
def __init__(self): 
    print "world" 

class B(A): 
def __init__(self): 
    print "hello" 
    A.__init__(self) 
+0

Esto no funcionará para las nuevas clases de estilo? – kdbanman

+4

@kdbanman: Esto funcionará con las clases de estilo nuevo, pero una de las razones para usar las clases de estilo nuevo es no tener que hacerlo de esta manera. Puede usar 'super' y no tiene que nombrar directamente la clase de la que está heredando. – Gabe

28

Una forma es para llamar al constructor de A y pase self como argumento, como lo siguiente:

class B(A): 
    def __init__(self): 
     A.__init__(self) 
     print "hello" 

La ventaja de este estilo es que está muy claro. Llama al constructor de A. La desventaja es que no maneja la herencia en forma de diamante muy bien, ya que puede terminar llamando al constructor de la clase base compartida dos veces.

Otra forma es usar super(), como otros han mostrado. Para la herencia única, básicamente hace lo mismo que permitirte llamar al constructor del padre.

Sin embargo, super() es un poco más complicado bajo el capó y en ocasiones puede ser contradictorio en situaciones de herencia múltiple. En el lado positivo, super() se puede utilizar para manejar la herencia en forma de diamante. Si quieres saber los detalles de lo que hace super(), la mejor explicación que he encontrado sobre cómo funciona super() es here (aunque no estoy necesariamente respaldando las opiniones de ese artículo).

86

En línea con las otras respuestas, hay varias maneras de llamar a los métodos de superclase (incluyendo el constructor), sin embargo en Python 3.x el proceso se ha simplificado:

Python 2.x

class A(object): 
def __init__(self): 
    print "world" 

class B(A): 
def __init__(self): 
    print "hello" 
    super(B, self).__init__() 

Python-3.x

class A(object): 
def __init__(self): 
    print("world") 

class B(A): 
def __init__(self): 
    print("hello") 
    super().__init__() 

super() ahora es equivalente a super(<containing classname>, self) según the docs.

4

que utilizar la siguiente fórmula que se extiende respuestas anteriores:

class A(object): 
def __init__(self): 
    print "world" 

class B(A): 
def __init__(self): 
    print "hello" 
    super(self.__class__, self).__init__() 

B() 

De esta manera usted no tiene que repetir el nombre de la clase en la llamada a súper. Puede ser útil si está codificando un gran número de clases y desea hacer que su código en los métodos de construcción sea independiente del nombre de la clase.

+4

Pero obtendrá recursión infinitiva si decide extender 'B' con' C', y 'self .__ class__' apunta a' C (B) 'en lugar de' B (A) ', así' super (self .__ class__, self) 'apunta a' B' en lugar de 'A'. – dened

+7

Esto dará lugar a infinitos errores de recursión cuando subclases 'B'. No ** use ** 'self .__ class__' o' type (self) ', pase una clase explícita (' B' aquí) o, en Python 3, use 'super()' sin argumentos. –

Cuestiones relacionadas