Re: [Python] Ereditarietà tra classi: un semplice esempio pratico da chiarire
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 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__
Re: [Python] Ereditarietà tra classi: un semplice esempio pratico da chiarire
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/mail
Re: [Python] Ereditarietà tra classi: un semplice esempio pratico da chiarire
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"? Ti ringrazio. Marco ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Ereditarietà tra classi: un semplice esempio pratico da chiarire
On 2014-11-21 17:35, Daniele Varrazzo wrote: On 2014-11-21 17:19, Marco Ippolito wrote: class Sub(Super): def __init__(self, indirizzo,cosa_fa): Super.__init__(self, nome, cognome, indirizzo) self.cosa_fa = cosa_fa ... ora... No, anche prima... se modifico la Sub class in questo modo: class Sub(Super): def __init__(self, cosa_fa): Super.__init__(self, nome, cognome, citta) self.cosa_fa = cosa_fa Ne' questo ne' quello di sopra sono corretti. Forse hai delle variabili globali che accidentalmente si chiamano nome e cognome ma non ne hai una che si chiama citta. Ah si`, giusto: le variabili sono definite qui: if __name__ == '__main__': nome = 'Marco' cognome = 'Ippolito' Il costruttore accidentalmente pesca questi valori dal namespace globale. Questo e` un comportamento sbagliato. Chiamale in un altro modo e vedrai che avrai un'eccezione anche nel primo caso. -- Daniele ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Ereditarietà tra classi: un semplice esempio pratico da chiarire
On 2014-11-21 17:19, Marco Ippolito wrote: class Sub(Super): def __init__(self, indirizzo,cosa_fa): Super.__init__(self, nome, cognome, indirizzo) self.cosa_fa = cosa_fa ... ora... No, anche prima... se modifico la Sub class in questo modo: class Sub(Super): def __init__(self, cosa_fa): Super.__init__(self, nome, cognome, citta) self.cosa_fa = cosa_fa Ne' questo ne' quello di sopra sono corretti. Forse hai delle variabili globali che accidentalmente si chiamano nome e cognome ma non ne hai una che si chiama citta. nome e cognome sono variabili locali: le devi passare al costruttore di sub, che nel primo caso potrebbe essere ad esempio: class Sub(Super): def __init__(self, nome, cognome, indirizzo, cosa_fa): Super.__init__(self, nome, cognome, indirizzo) self.cosa_fa = cosa_fa Il secondo caso "funziona bene", ovvero ti da` un errore. Anche il primo dovrebbe. -- Daniele ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
[Python] Ereditarietà tra classi: un semplice esempio pratico da chiarire
Ciao a tutti, con l'obiettivo di capire fino in fondo alcuni aspetti dell'ereditarietà tra classi che non mi sono ancora chiari (pensavo lo fossero), mi sono scritto un esempio forzatamente banale. #!/usr/bin/python class Super: def __init__(self, nome, cognome, citta): self.nome = nome self.cognome = cognome self.citta = citta self.nome_intero = '%s %s' % (self.nome, self.cognome) def super_meth_1(self): return '%s abita a %s' % (self.nome_intero, self.citta) def get_super_result(self): return self.super_meth_1() class Sub(Super): def __init__(self, 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 = 'Marco' cognome = 'Ippolito' abita = 'Milano' super_class = Super(nome, cognome, abita) ris_super = super_class.get_super_result() print 'ris_super: ', ris_super cosa = 'suona' sub = Sub(abita, cosa) 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 time ./classInheritage2.py ris_super: Marco Ippolito abita a Milano ris_sub_1: Marco Ippolito suona ris_sub_2: Marco Ippolito abita a Milano ora... se modifico la Sub class in questo modo: #!/usr/bin/python class Super: def __init__(self, nome, cognome, citta): self.nome = nome self.cognome = cognome self.citta = citta self.nome_intero = '%s %s' % (self.nome, self.cognome) def super_meth_1(self): return '%s abita a %s' % (self.nome_intero, self.citta) def get_super_result(self): return self.super_meth_1() class Sub(Super): def __init__(self, cosa_fa): Super.__init__(self, nome, cognome, citta) 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 = 'Marco' cognome = 'Ippolito' abita = 'Milano' super_class = Super(nome, cognome, abita) ris_super = super_class.get_super_result() print 'ris_super: ', ris_super cosa = 'suona' sub = Sub(cosa) 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 l'ouput risulta: ris_super: Marco Ippolito abita a Milano Traceback (most recent call last): File "./classInheritage3.py", line 37, in sub = Sub(cosa) File "./classInheritage3.py", line 18, in __init__ Super.__init__(self, nome, cognome, citta) NameError: global name 'citta' is not defined Cosa differenzia l'attributo "citta" dagli altri attributi ("nome" e "cognome") anche essi presenti in Super class? Qual è il modo corretto per far sì che Sub class erediti da Super class gli attributi "nome, "cognome" e "citta" ? Marco ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] Python e saturazione CPU
Il giorno 21 novembre 2014 00:03, Enrico Bianchi ha scritto: > >> Per la chiusura dei file, suggerirei di usare il costrutto with: > > with open(filein, 'r') as fin, open(writeto + fileout, "w") as fou: > #resto del codice Per prima cosa GRAZIE a tutti. Il problema, come sospettavo, in realta' era sulla vm. Ho abilitato l'accelerazione 3D per lo schermo e il problema e' sparito. Ciao. -- Riccardo Brazzale ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python
Re: [Python] ctypes e puntatore ad un array di stringhe
On Tue, Nov 18 2014, Marco Giusti wrote: > Salve a tutti, > > con ctypes vorrei richiamare una funzione C che ritorna **char. La > funzione in causa assegna la memoria per le singole stringhe e per > l'array stesso e lascia al chiamante l'onere di liberarla. Sebbene con > ctypes riesca ad accedere ai singoli valori, non riesco ad accedere > all'area di memoria puntate e di conseguenza non riesco a liberarla. Penso di aver risolto giocando con i puntatori come in C. Spero di non andare all'inferno per questo .) Per la cronaca allego quanto fatto così, se avete voglia, potete anche verificare la correttezza. m. #include #include #include "my.h" int main(int argc, char *argv[]) { char **env = NULL; int i; if ((env = getlist()) == NULL) { perror("getlist"); exit(1); } for (i=0; env[i] != NULL; i++) printf("%s\n", env[i]); exit(0); } all: libmy.so a.out run: libmy.so LD_LIBRARY_PATH=. python my.py libmy.so: my.c my.h gcc -Wall -fPIC -g -c my.c gcc -shared -Wl,-soname,libmy.so.1 -o libmy.so.1.0 my.o ln -sf libmy.so.1.0 libmy.so.1 ln -sf libmy.so.1 libmy.so a.out: libmy.so main.c gcc -Wall -I. -L. -lmy -g main.c clean: rm my.o a.out libmy.so* #include #include char **getlist(void) { char **env = NULL; if ((env = malloc(3 * sizeof(char *))) != NULL) { env[0] = NULL; env[1] = NULL; env[2] = NULL; if ((env[0] = strdup("hello")) != NULL) { if ((env[1] = strdup("world")) != NULL) return env; else free(env[0]); } free(env); } return NULL; } char **getlist(void); import ctypes import ctypes.util _libmy = ctypes.CDLL("libmy.so.1") _libc = ctypes.CDLL(ctypes.util.find_library("c")) _sizeof_pointer = ctypes.sizeof(ctypes.c_void_p) def getlist(): arr = _libmy.getlist() ret = [] off = 0 p = ctypes.c_int.from_address(arr).value while p: ret.append(ctypes.string_at(p)) _libc.free(p) off += _sizeof_pointer p = ctypes.c_int.from_address(arr + off).value _libc.free(arr) return ret if __name__ == "__main__": print getlist() ___ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python