Mille grazie Daniele delle tue interessanti spiegazioni. Ammetto che non sapevo che si potesse usare un costrutto del tipo: class NomeClasse(Super): def __init__(self, variabili,....., **kwargs): super(NomeClasse, self).__init__(variab_super, **kwargs)
Hai ragione nel dire che se vengono passati tanti parametri alla classe, vuol dire che bisogna riguardare il codice, e magari suddividerlo in più classi. Marco Il 21 novembre 2014 20:41, Daniele Varrazzo <p...@develer.com> ha scritto: > On 2014-11-21 17:53, Marco Ippolito wrote: >> >> Ciao Daniele, >> ti ringrazio per l'aiuto. >> >> Ho modificato l'esempio, passando tutte le variabili locali (nome, >> cognome, citta) al costruttore di sub. E così funziona (come vedi >> sotto). >> >> #!/usr/bin/python >> >> class Super: >> def __init__(self, nome, cognome, indirizzo): >> self.nome = nome >> self.cognome = cognome >> self.indirizzo = indirizzo >> self.nome_intero = '%s %s' % (self.nome, self.cognome) >> >> def super_meth_1(self): >> return '%s abita in %s' % (self.nome_intero, self.indirizzo) >> >> def get_super_result(self): >> return self.super_meth_1() >> >> class Sub(Super): >> def __init__(self, nome, cognome, indirizzo, cosa_fa): >> Super.__init__(self, nome, cognome, indirizzo) >> self.cosa_fa = cosa_fa >> >> def sub_meth_1(self): >> return '%s %s' % (self.nome_intero, self.cosa_fa) >> >> def get_sub_meth_1(self): >> return self.sub_meth_1() >> >> >> if __name__ == '__main__': >> >> nome_f = 'Marco' >> cognome_f = 'Ippolito' >> abita_f = 'Milano' >> super_class = Super(nome_f, cognome_f, abita_f) >> ris_super = super_class.get_super_result() >> print "ris_super: ", ris_super >> cosa_f = 'suona' >> sub = Sub(nome_f, cognome_f, abita_f, cosa_f) >> ris_sub_1 = sub.get_sub_meth_1() >> print "ris_sub_1: ", ris_sub_1 >> ris_sub_2 = sub.get_super_result() >> print "ris_sub_2: ", ris_sub_2 >> >> ./classInheritage.py >> ris_super: Marco Ippolito abita in Milano >> ris_sub_1: Marco Ippolito suona >> ris_sub_2: Marco Ippolito abita in Milano >> >> C'è un modo per passare far sì che nel main passi a Sub solo le >> variabili che lo "differenziano" (specializzano) rispetto a Super? >> Cioè c'è un modo per far sì che io possa passare in "main" solo la >> variabile "cosa_f"? > > > Nel caso in esempio si fa male. Il pattern migliore e` quello di elencare > gli argomenti. > > La cosa comincia ad essere utile se stabilisci che i costruttori delle tue > classi debbano essere chiamati solo con argomenti keyword, ovvero, se > stabilisci che chiamerai > > sub = Sub(nome=nome_f, cognome=cognome_f, abita=abita_f, cosa_fa=cosa_f) > > allora puoi usare **kwargs e fare: > > class Super: > def __init__(self, nome, cognome, indirizzo): > self.nome = nome > self.cognome = cognome > self.indirizzo = indirizzo > self.nome_intero = '%s %s' % (self.nome, self.cognome) > > class Sub(Super): > def __init__(self, cosa_fa, **kwargs): > Super.__init__(self, **kwargs) > self.cosa_fa = cosa_fa > > considerando che tipicamente definirai il costruttore solo in un punto ma lo > chiamerai in diversi punti ti conviene essere piu` verboso nelle definizioni > degli __init__ e risparmiare nell'invocazioe, quindi lasciare le cose come > stanno. > > Questa non e` l'unica cosa che si potrebbe tenere in considerazione pero`. > Il tuo e` un esempio di studio, che non ha veri vincoli. In casi piu` reali > potresti avere una gerarchia di oggetti dove pochi argomenti (tipo fino a 3, > ma meno sono e meglio e`) andranno *sempre* specificati per ogni oggetto > della gerarchia, mentre ci puo` essere un turbinare di argomenti che sono a) > opzionali e b) specifici solo di certe sottoclassi. In questo caso il modo > migliore (secondo me, YMMV) di organizzare il codice e` quello di passare > gli argomenti fondamentali in maniera posizionale (potrebbero anche essere > passati con keyword, l'importante e` mantenere la possibilita` di fare > entrambe le cose) e usare **kwargs per tutti gli altri, in modo da ignorare > quelli che non si conoscono ma di propagarli. > > Per esempio (non testato, ovviamente): > > class Persona(object): > def __init__(self, nome): > self.nome = nome > > class Lavoratore(Persona): > def __init__(self, nome, ruolo, salario=None, **kwargs): > super(Lavoratore, self).__init__(nome, **kwargs) > self.ruolo = ruolo > self.salario = salario > > class Studente(Persona): > def __init__(self, nome, scuola, classe=None, **kwargs): > super(Studente, self).__init__(nome, **kwargs) > self.scuola = ... > > class StudenteUniversitario(Studente): > def __init__(self, nome, fuoricorso_dal=None, **kwargs): > super(StudenteUniversitario, self).__init__(nome, **kwargs) > ... > > Il nome puoi passarlo con keyword o meno, gli altri argomenti devono avere > una keyword. > > p1 = StudenteUniversitario("Tizio Caio", scuola="Anormale", > fuoricorso_dal=1996) > p2 = Lavoratore(nome="Pinco Pallini", ruolo=...) > > > Avere classi che richiedono un gran numero di parametri posizionali da > passare non e` una buona cosa: e` facile sbagliare nel passaggio. Se gli > argomenti cominciano ad essere tanti e` meglio richiedere che vengano > passati con keyword (ma e` ancora meglio chiedersi come mai ci siano tanti > parametri e cambiare qualcosa nel codice). > > > > -- Daniele > > _______________________________________________ > Python mailing list > Python@lists.python.it > http://lists.python.it/mailman/listinfo/python _______________________________________________ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python