2015-05-15 8 views
10

Sto creando una GUIclass che utilizza Frame() come classe base.Classi Python: Ereditarietà vs Istanziazione

Nel mio metodo init di GUIclass voglio creare un widget frame

In questo momento ho:

class GUIclass(Frame): 
    def __init__(self, parent): 
     frame = Frame(self, parent) 

Ma ho visto questo altrove per la terza linea:

Frame.__init__(self, parent) 

Sono un neofita della programmazione, python e sicuramente ereditarietà e volevo sapere se ho compreso correttamente la differenza tra i due. Ho fatto molte ricerche e letture, lo prometto, ma non sono riuscito a trovare nulla che lo rendesse completamente chiaro:

Nella prima situazione non chiamo il metodo init come ho creato un oggetto Frame (frame) e quando viene creato un oggetto, il suo metodo init viene chiamato implicitamente da python.

Nel secondo scenario, si chiama il metodo init sulla classe (che credo sia del tutto legittimo?) Perché non è stato creato un oggetto Frame, pertanto non lo farebbe automaticamente.

È giusto?

Ho visto anche:

frame = Frame.__init__(self, parent) 

che in realtà mi ha buttato fuori. È solo qualcuno che fa qualcosa di ridondante o c'è una ragione per questo?

Grazie per il vostro aiuto, voglio prenderlo lentamente per ora e assicurarmi di comprendere appieno ogni riga di codice che scrivo mentre vado piuttosto che scrivere e far girare un intero programma che ho capito a metà.

+0

Si consiglia di utilizzare il secondo: 'Telaio .__ init __ (self, genitore)' –

+2

Il primo è semplicemente non corretta in quanto crea un inutile frame nell'inizializzatore di un oggetto basato su frame. –

+0

Il secondo e il terzo sono super chiamate all'inizializzatore padre nel frame, in modo tale che l'inizializzatore della classe figlio estenderà le basi, non sovrascrive le basi. Ma non è necessario assegnare il risultato di una super chiamata rendendo il terzo errato. –

risposta

8

si dovrebbe chiamare

super(GUIclass, self).__init__(parent) 

Questo è il modo corretto di chiamare (tutti) la tua __init__() metodo (s) ereditato. Si è in molti casi risultati identici rispetto al citato

Frame.__init__(self, parent) 

cui manca solo l'astrazione per quanto riguarda le relazioni di ereditarietà e dichiara la classe Frame come la sola e unica classe la cui __init__() metodo si potrebbe desiderare di chiamare il numero (di più su questo dopo).

Il citato anche

frame = Frame(self.parent) 

è sbagliato in questo contesto. Appartiene a un altro modello di relazione oggetto, ovvero contenuto relazione anziché ereditarietà relazione (a cui si mira). Sarà creare un nuovo oggetto della classe Frame invece di inizializzare le parti di Frame; nelle relazioni di ereditarietà sono a Frame, quindi è necessario inizializzare yourself e inizializzare le parti specializzate (che viene eseguito nel resto del metodo __init__()).Nei modelli di rapporto si tratta semplicemente di a Frame.

Ora, che dire di quella "leggera" differenza che ho menzionato sopra chiamando il numero super(GUIclass, self).__init__(parent) e Frame.__init__(self, parent)?

Per capire che è necessario approfondire le relazioni di ereditarietà e le varie possibilità offerte, in particolare con l'ereditarietà multipla.

Si consideri un modello di relazione a forma di diamante che assomiglia a questo:

  Frame 
     / \ 
    GUIclass SomeOtherClass 
      \ /
     AnotherClass 

Nel suo scenario attuale si ha solo la parte superiore ha lasciato due classi, ma non si sa mai cosa sta per venire, e si dovrebbe sempre il codice in un modo tale che il prossimo utente del tuo codice conservi tutte le opzioni.

In questo schema a forma di diamante si ha AnotherClass che eredita GUIClass e SomeOtherClass che a loro volta ereditano entrambi Frame.

Se ora si utilizza il modello Frame.__init__(self, parent) sia GUIclass e SomeOtherClass, quindi chiamando i loro __init__() metodi dal metodo AnotherClass__init__() si tradurrà in una chiamata raddoppiata del metodo di 's il Frame__init__(). Questo in genere non è previsto, e per fare in modo che ciò non accada, è stata inventata la chiamata super. Ci si assicura che un decente ordine di chiamata chiama ciascuno dei metodi __init__() solo ed esattamente una volta.

+0

Gli argomenti 'super' vanno nell'altro ordine. – user2357112

+0

Grazie, risolto quello. (Non li ricordo mai correttamente, quindi se mi hai fregato, l'ho proprio disapprovato ;-) – Alfe

+0

Ah adesso tutto ha senso ora, penso di vedere la differenza. Quindi, dovrei essere corretto nel dire che il primo inizializza tecnicamente un frame, ma crea un oggetto frame separato invece di dire che questo oggetto ha queste proprietà frame e poi alcuni - l'allora alcuni sono qualsiasi cosa nelle classi child __init__? – Burkely91

1

Dovrete usare Frame.__init__(self, parent) come Tkinter non supporta le chiamate super-