2013-01-07 16 views
33

In Python, come scegliere quale metodo di Parent chiamare? Dire che voglio chiamare il metodo __init__ del padre ASDF2. Sembra che devo specificare ASDF1 nel super() ..? E se voglio chiamare ASDF3 __init__, allora devo specificare ASDF2?!Ereditarietà di Python: scegliere quale super() chiamare

>>> class ASDF(ASDF1, ASDF2, ASDF3): 
    def __init__(self): 
     super(ASDF1, self).__init__() 


>>> ASDF() 
ASDF2's __init__ happened 
>>> class ASDF(ASDF1, ASDF2, ASDF3): 
    def __init__(self): 
     super(ASDF2, self).__init__() 


>>> ASDF() 
ASDF3's __init__ happened 

Sembra matto per me. Che cosa sto facendo di sbagliato?

risposta

47

Questo non è quello che è super(). Super fondamentalmente sceglie uno (o tutti) i suoi genitori in un ordine specifico. Se si desidera solo di chiamare il metodo di un singolo genitore, fare questo

class ASDF(ASDF1, ASDF2, ASDF3): 
    def __init__(self): 
     ASDF2.__init__(self) 
10

super chiama il metodo successivo in ordine di risoluzione metodo. In un albero di ereditarietà lineare, questo sarà il metodo dalla classe immediatamente genitore.

Qui ci sono tre genitori e il successivo metodo __init__ dal punto di vista ASDF1 è quello di ASDF2. In generale, la cosa sicura da fare è passare la prima classe dell'elenco di eredità a super a meno che non si sappia perché si desidera fare qualcos'altro.

Il punto di tutto questo è quello di sollevare l'utente dal dover scegliere esplicitamente quali metodi __init__ chiamare. La domanda qui è perché non si desidera chiamare tutti i metodi della superclasse __init__.

C'è una letteratura abbastanza consistente sull'uso di super in python, e vi consiglio di google l'argomento e di leggere quali risultati.

4

Si passa ASDF1 (una delle classi genitore) come primo argomento a super(). Non farlo. Invece, dovresti passare ASDF come primo argomento a super().

Python 2.7 documentation for super()

Per citare la documentazione Python 2.7, una tipica chiamata superclasse assomiglia a questo:

class C(B): 
    def method(self, arg): 
     super(C, self).method(arg) 

Si noti che il primo argomento a super qui è C, che è la classe corrente. Non passare B (la classe genitore) a super().

Durante la determinazione del metodo Risoluzione ordine (MRO), viene superata la classe passata come primo argomento e inizia a esaminare i genitori e i fratelli di quella classe. Quindi, quando hai passato ASDF1 come primo argomento a super(), è saltato su ASDF1 e ha iniziato la sua ricerca con ASDF2. Ecco perché è stato chiamato il numero __init__ di ASDF2.


In Python 3, non è più necessario passare la classe corrente.

class C(B): 
    def method(self, arg): 
     super().method(arg) # This does the same thing as: 
           # super(C, self).method(arg) 
           # (Python 3 only) 
Problemi correlati