2015-01-14 15 views
9

La documentazione di Python 2 dice che la funzione super()"restituisce un oggetto proxy che delega le chiamate di metodo a una classe di tipo padre o fratello".Che cos'è una classe di pari livello in Python?

Le domande:

  1. Che è una classe di pari livello in Python?
  2. Come si delega una chiamata di metodo a una classe di pari livello?

La mia presunzione era che un fratello per una data classe è una classe che eredita dallo stesso genitore. Ho redatto il seguente codice per vedere come una chiamata al metodo può essere delegata a un fratello, ma non ha funzionato. Cosa faccio o capisco male?

+0

Non ho tempo di scrivere una risposta completa, ma penso che i documenti si riferiscano all'ereditarietà multipla. Se la classe C eredita sia da A che da B, potresti considerare A e B come "fratelli" in un certo senso. 'super()' chiama nel corpo di A su un'istanza di C delegherà a B. Vedi [questa domanda] (http://stackoverflow.com/questions/3277367/how-does-pythons-super-work-with -multiple-inheritance) per il low-down. –

+1

La risposta accettata a questa domanda qui spiega i dettagli di come 'super()' può effettivamente chiamare le classi genitore ma anche fratello: http://stackoverflow.com/questions/5033903/python-super-method-and-calling-alternatives –

+0

@SimeonVisser, ho visto quella domanda, anche recitato. Non dà una risposta chiara a ciò che è una classe di fratello. Questa domanda è correlata a quella, ma chiaramente non è un duplicato. – golem

risposta

5

Dopo qualche ulteriore ricerca e la lettura Python’s super() considered super! articolo sono arrivato alle seguenti conclusioni:

  1. Una classe di pari livello è quello che pensavo che fosse. È una classe che eredita dallo stesso genitore. È la definizione della documentazione di Python che mi ha buttato fuori strada. Sembra che quando la documentazione di Python dice che le chiamate al metodo delegate a una classe genitore o sorella significano a un genitore o fratello di un genitore che è anche una classe base di un dato bambino. Quella è un'eredità del diamante che deve aver luogo.

  2. super() delegati di funzione una chiamata di metodo alla classe fratello di un genitore automaticamente in base MRO (ordine di risoluzione metodo).

Ecco un caso interessante che ho trovato mentre sperimentando con super() funzione:

class Class0(object): 
    def MethodA(self): 
     print("MethodA of Class0") 

class ClassA(Class0): 
    def MethodA(self): 
     super(ClassA, self).MethodA() 
     print("MethodA of ClassA") 

class ClassB(Class0): 
    def MethodA(self): 
     print("MethodA of ClassB") 

class ClassC(ClassA, ClassB): 
    def MethodA(self): 
     super(ClassC, self).MethodA() 

if __name__ == '__main__': 
    ClassC().MethodA() 

Il codice stamperà

MethodA of ClassB 
MethodA of ClassA 

Se si come mi chiedo perché MethodA di class0 non viene mai stampato, ecco la spiegazione come la capisco. L'MRO del ClassC stampato con print(ClassC.__mro__) è

(<class '__main__.ClassC'>, <class '__main__.ClassA'>, <class '__main__.ClassB'>, <class '__main__.Class0'>, <class 'object'>).

Ora se si segue l'MRO, la funzione super() di MethodA() di ClassC chiamerà il metodoA() di ClassA, che prima della stampa chiamerà MethodA() di classB (poiché è successivo in MRO) E MethodA() di ClassB a sua volta stamperà ed uscirà dal momento che non usa la funzione super() per delegare la chiamata al metodo sulla catena MRO.

0

Un fratello è una classe con lo stesso genitore, come sospettavate. Il caso che ti manca è che super potrebbe chiamare un metodo fratello se questa classe si è moltiplicare ereditato da:

class A(object): 
    def something(self): 
    print("A") 
class B(A): 
    def something(self): 
    print("B") 
class C(A): 
    def something(self): 
    print("C, about to call super()") 
    super(C, self).something() 
class D(C, B): 
    def something(self): 
    super(D, self).something() 

>>> D().something() 
C, about to call super() 
B 

In C, abbiamo chiamato super(), ma abbiamo ottenuto B - che è un fratello, non un genitore e non genitore di un fratello, ma un fratello diretto effettivo di C.

+0

Grazie, sono giunto alla stessa conclusione. Penso che la definizione più precisa sarebbe * il fratello genitore che è anche una classe base di un dato bambino * - la definizione che ho usato nella mia risposta. – golem

+0

No, non è una definizione precisa. 'B' non è il fratello * di un genitore * di' C'. È un * fratello * di 'C'. – lmm

+0

B è un primo genitore, C è un secondo genitore. B e C sono fratelli. In * parent's sibling che è anche una classe base di un dato figlio * sostituto e otterrai: fratello di B che è anche una classe base di D. C =). – golem

Problemi correlati