2011-02-08 21 views
7

Spero che questo è abbastanza chiaro:Python: Ottenere valori BaseClass dalla classe derivata

class myParent(): 
    def __init__(self): 
     self.parentNumber = 5 

class Child(myParent): 
    def __init__(self): 
     self.childNumber = 4 

    def multiplyNumbers(self): 
     print myParent.parentNumber * self.childNumber 

p = Child() 
p.multiplyNumbers() 

desidero impostare il parentNumber individualmente, e quindi raggiungere quel numero tramite la classe del bambino, e in questo caso usarlo per un po ' moltiplicazione.

Sono nuovo nell'area OOP quindi qualsiasi suggerimento generale sull'ereditarietà è ben accetto!

Maggiori informazioni: Sto progettando una soluzione di gestione del progetto per i progetti di VFX-based, e sto giocando con le classi e l'ereditarietà per vedere come mi possono aiutare i più.

In questo momento, ho ottenuto la classe superiore, Project e una classe derivata, Shot. Il colpo ha una variabile autofiorente con la lunghezza dello sparo specifico. Ha anche un metodo getLengthInSeconds() che usa self.length insieme a Project.fps per determinare la lunghezza in secondi. Project ha un metodo setFps() in cui viene impostato l'fps dopo che è stata creata un'istanza della classe.

Sono abituato alle variabili che sono prefissate con il sé. e non ho mai sperimentato molto con le classi usando le variabili più "globali" senza auto. . Se creo tutto ciò che è globale, non me stesso, posso usare Project.fps senza problemi, ma ricevo un avviso di "cattiva programmazione" nella mia nuca. Forse c'è un modo migliore, più pulito?

Edit:

Dopo qualche lettura, super() sembra un pò pericoloso, e un po 'più di quello che serve penso. Ho principalmente classi di ereditarietà e non sono nemmeno sicuro di come utilizzare le gerarchie di diamanti. Esiste un modo più sicuro per accedere a variabili e metodi della superclasse che non includono super()?

Edit:

Allright, vedere se questo ha un senso o se sto pensando di sbagliato tutto.

Sto guardando le classi e l'ereditarietà come gruppi e bambini. Un bambino sa che è un genitore e tutti i suoi valori. Un figlio di un altro genitore sa che i valori dei genitori. Quello che sto cercando di realizzare è avere tutti gli scatti creati come parte di un progetto. E proprio ora sto creando istanze Shot() dalla classe Project(), aggiungendo le istanze a un elenco di scatti che viene poi mantenuto all'interno dell'istanza Project().

cioè

class myParent(object): 
    def __init__(self): 
     self.parent_id = '' 
     self.children = [] 

    def createChild(self, name): 
     self.children.append(myChild(name)) 

    def getChildren(self): 
     return self.children 

    def setParentId(self, id): 
     self.parentId = id 

class myChild(myParent): 
    def __init__(self, id): 
     super(myChild, self).__init__() 
     self.id = id 

    def getParentId(self): 
     return self.parent_id 

p = myParent() 
p.setParentId('parent01') 
p.createChild('child01') 
print p.getChildren()[0].getParentId() 

posso sorta di vedere i mis-passi in logica qui, ma nessun vero modo intorno ad esso .. sembra che ogni bambino è sempre una nuova istanza del genitore in questo modo, in cui parent_id è sempre una stringa vuota.

+0

è necessario chiamare il costruttore della superclasse. –

risposta

5
class myParent(object): 
    def __init__(self): 
     self.parentNumber = 5 

class Child(myParent): 
    def __init__(self): 
     myParent.__init__(self) 
     self.childNumber = 4 

    def multiplyNumbers(self): 
     print self.parentNumber * self.childNumber 

p = Child() 
p.multiplyNumbers()

Di solito è possibile gestire bene senza super quando non si dispone di ereditarietà multipla o di altri casi di confine , sebbene se la classe base cambia, sarà necessario ricordare di cambiare il nome della classe genitore da init (e qualsiasi altro metodo che fa riferimento a myParent in modo esplicito).

Se il parametro __init__ del genitore utilizza i parametri, è necessario passarli dal __init__ del minore.

class myParent(object): 
    def __init__(self, customParam): 
     self.parentNumber = 5 
     self.customParam = customParam 

class Child(myParent): 
    def __init__(self, customParam): 
     myParent.__init__(self, customParam) 
     self.childNumber = 4

Se non ti piace la ripetizione di customParam in tutte le classi dei bambini, c'è un modello alternativo OO chiamato due fase di costruzione, che funziona così:

class myParent(object): 
    def customInit(self, customParam): 
     self.parentNumber = 5 
     self.customParam = customParam 

class Child(myParent): 
    def __init__(self, customParam): 
     self.childNumber = 4 

p = Child() 
p.customInit(10) 
p.multiplyNumbers() 

In questo modello, non è necessario per ripetere uno dei parametri del genitore, o anche chiamare il genitore __init__ nel bambino, ma lo svantaggio è che dovrai ricordarti di chiamare sempre il costruttore secondario quando crei oggetti, altrimenti il ​​tuo oggetto sarà parzialmente non inizializzato.

UPDATE (per rispondere alla domanda aggiornato):

Sembra che tu stia mescolando due concetti indipendenti di genitorialità qui. L'ereditarietà riguarda la gerarchia di tipi e sembra che tu sia dopo una gerarchia di proprietà (is-a versus ha-a).

vorrei strutturare il codice aggiornato in questo modo:

class myParent(object): 
    def __init__(self, parentId): 
     self.id = parentId 
     self.children = [] 

    def createChild(self, name): 
     self.children.append(myChild(name, self)) 

    def getChildren(self): 
     return self.children 

class myChild(object): 
    def __init__(self, childId, parent): 
     self.id = childId 
     self.parent = parent 

    def getParentId(self): 
     return self.parent.id 

p = myParent('parent01') 
p.createChild('child01') 
print p.getChildren()[0].getParentId()
+0

Grazie per la tua risposta! Ti dispiacerebbe dare un'occhiata alla domanda aggiornata? –

+0

@Marcus: aggiornata la risposta – shang

+0

Sì, questo ha molto più senso. Grazie! –

5

Hai solo bisogno di dire Child per eseguire l'inizializzazione da myParent. Successivamente, l'istanza corrente (self) ha tutti gli attributi di istanza avrebbe un'istanza di myParent ("is a"), quindi è possibile utilizzare self.parentNumber. Lo fai inserendo super(Child, self).__init__() in Child.__init__ (idealmente, nella prima riga) - myParent.__init__(self) funzionerebbe, ma potrebbe essere sbagliato (in modo sottile) quando la classe base cambia o in caso di ereditarietà multipla. Puoi lasciare cadere tutti gli argomenti su super se stai usando Python 3.

Si noti inoltre che

class C(object): 
    x = ... 

è molto diverso da

class C(object): 
    def __init__(self): 
     self.x = ... 

Il primo crea una variabile di classe, che è condiviso da tutte le istanze di C. Quest'ultimo crea una variabile di istanza, ogni istanza di C ha il proprio. (Allo stesso modo, le variabili globali non sono vincolati alle istanze - ma suppongo tu parlavi di cui sopra?)

+1

+1 .. e dovrebbe essere 'self.parentNumber' in' multiplyNumbers'. – sdolan

+0

@sdolan: Sì, incluso. – delnan

+0

Proprio il tipo di informazioni che stavo cercando. Ci proverò. –

Problemi correlati