2011-11-04 14 views
8

Eventuali duplicati:
Can Super deal with multiple inheritance?chiamata init per più classi genitore con super?

Python eredità? Ho una struttura di classe (in basso), e voglio che la classe figlia per chiamare il __init__ di entrambi i genitori. È possibile farlo in modo "super" o è solo una pessima idea?

class Parent1(object): 
    def __init__(self): 
     self.var1 = 1 

class Parent2(object): 
    def _init__(self): 
     self.var2 = 2 

class Child(Parent1, Parent2): 
    def __init__(self): 
     ## call __init__ of Parent1 
     ## call __init__ of Parent2 
     ## super(Child, self).__init__() 

risposta

17

Invocazione via super non chiama tutti i genitori, chiama la funzione successiva nella catena MRO. Per farlo funzionare correttamente, è necessario utilizzare super in tutte le __init__ s:

class Parent1(object): 
    def __init__(self): 
     super(Parent1, self).__init__() 
     self.var1 = 1 

class Parent2(object): 
    def __init__(self): 
     super(Parent2, self).__init__() 
     self.var2 = 2 

class Child(Parent1, Parent2): 
    def __init__(self): 
     super(Child, self).__init__() 

In Python 3, è possibile utilizzare al posto di super()super(type, instance).

+0

Ho letto molte altre domande e risposte, il tuo è l'unico che ha sottolineato come 'super()' definisce la "funzione successiva nella catena MRO". Una dichiarazione semplice ma molto importante. – MikeyE

26

L'idea di super() è che non c'è bisogno di preoccuparsi di chiamare __init__() metodi entrambe le superclassi separatamente - super() si prenderà cura di esso, a condizione di utilizzare in modo corretto - vedi Raymond Hettinger's "Python’s super() considered super!" per una spiegazione.

Detto questo, trovo spesso gli svantaggi di super() per le chiamate costruttore troppo elevati rispetto ai vantaggi. Ad esempio, tutti i costruttori devono fornire un ulteriore argomento **kwargs, tutte le classi devono collaborare, le classi esterne non collaborative necessitano di un wrapper, occorre fare attenzione che ciascun nome del parametro del costruttore sia univoco attraverso tutte le classi, ecc.

Così il più delle volte, penso che sia più facile dare un nome in modo esplicito i metodi della classe di base che si desidera chiamare per costruzione chiama:

class Child(Parent1, Parent2): 
    def __init__(self): 
     Parent1.__init__(self) 
     Parent2.__init__(self) 

io faccio uso super() per le funzioni che hanno un prototipo garantito, come __getattr__() , anche se. Non ci sono svantaggi in questi casi.

7

Si potrebbe semplicemente chiamarli direttamente con Parent.__init__(self):

class Parent1(object): 
    def __init__(self): 
        self.var1 = 1 

class Parent2(object): 
    def _init__(self): 
        self.var2 = 2 

class Child(Parent1, Parent2): 
    def __init__(self): 
     Parent1.__init__(self) 
     Parent2.__init__(self) 
Problemi correlati