On Dec 26, 2007 11:47 AM, ugaciaka <[EMAIL PROTECTED]> wrote: > Riassumendo: ho scritto un programmino (senza nessuna classe ma con > sole funzioni), ho notato che se passo da paramentro una variabile per > fargli capire al compilatore che non è una variabili d'istanza (cioé > della funzione) ma di tutto del corpo del programma devo anteporre > global al nome della variabile passata.
Allora, affrontiamo la cosa su due piani distinti. Primo piano: 1. evitare le variabili globali quanto più possibile. tu non hai bisogno di usare variabili globali. *NON* usarle. 2. veniamo al significato del concetto di global (lo statement, intendo). Come ti sarai reso conto in Python le dichiarazioni *non* esistono. Le variabili quando le vuoi, le usi. Le variabili tipicamente hanno due stati 'bound' e 'unbound'. Dopo un assegnamento una variabile è bound all'oggetto che le è stato assegnato. Se semplicemente uso una variabile unbound (un nome 'vuoto') per esempio chiamando dei metodi, ho degli errori. A questo punto veniamo al concetto di global. def foo(i): return a * i a = 5 print foo(2) Stampa chiaramente 10. Quando va a cercare la variabile 'a' la trova (nello scope globale) e usa quella. Il problema è invece quando io ho un assegnamento. Consideriamo questo frammento: def foo(i): return a * i def goo(): a = 3 return a a = 5 print foo(2) goo() print foo(2) Immagina che casino sarebbe se goo senza dire niente a nessuno *modificasse* una variabile globale solo perchè ne trova una. La chiamata della funzione non sarebbe più indipendente dal contesto (il caso di foo è diverso, è vero che è dipendente dal contesto pure lei, ma non modifica proditoriamente lo stato del programma, al limite fallisce se chiamata in uno scope inadatto, ma questo è un problema comune a tutte le funzioni che usano variabili globali, per inciso se goo andasse a modificare a, si avrebbero alcuni dei problemi presenti con i linguaggi che usano lo scope dinamico). Bene: a questo punto entra in gioco global. Se io dentro goo scrivo 'global a' sto dicendo *esplicitamente* che non mi deve fare il binding di una variabile locale chiamata a con l'oggetto 3, ma deve fare il binding della variabile globale a con l'oggetto 3 (si, il numero 3 è un oggetto). > Ok fin qua ci sono. Ma se io volessi ora mettere tutto in una classe > come agisco? Dove definisco le variabili globali? Nella classe? > All'interno del costruttore?... Scusa, ma io qui intravedo notevole confusione (al di la di Python o Java). Una variabile globale è globale, non è in un oggetto. Se no parliamo di variabili membro, campi, variabili d'istanza, whatever, oppure variabili di classe (se sono appunto legate alla classe e non alle istanze). > Il mio programmino di esercizio è questo sotto e praticamente non fa > altro che sostituire il carattere "_" con uno spazio " ". Ok, mi permetto di indirizzarti un pochetto sulla buona strada. 1. la nomenclatura delle funzioni è atroce. è faticosa da leggere e poco elegante 2. no globali please (specie in quanto risolvi il problema aggiungendo semplicemente un parametro per funzione, mica 54) 3. la funzione 'rinomina file' è in buona sostanza inutile. ha praticamente la stessa complessità dello statement che contiene, non astrae molto e non semplifica. questo è comunque opinabile. io personalmente preferisco leggere replace("_", " ") che andare a scoprire cosa si intende con 'rinomina'. 4. i cicli for sono allucinanti e poco efficienti. In Python puoi usare l'idioma for item in lista: # do something with item Gli inserimenti in mezzo alla lista sono molto meno efficienti degli inserimenti in coda. 5. perchè passare l'albero? non è meglio lasciare tutta la logica dentro il metodo? > #COSA INVECE VORREI FARE > #io vorrei invece fare solo, dopo aver creato la classe che ingloba i > miei metodi: > #oggetto=Classe(carattere_da_sostituire, carattere_sostituito) > #oggetto.rinomina_file() Qualcosa tipo questo? (non è testato, se noti le chiamate di sistema sono commentate, prova pure) import os from os.path import join class TermUI(object): """This class is responsible to present info to the user on a terminal.""" @classmethod def error(self, *message_parts): print ' '.join(message_parts) @classmethod def info(self, *message_parts): print ' '.join(message_parts) class Renamer(object): """A simple example class which renames files in a directory""" def __init__(self, old, new, ui=TermUI): self.old = old self.new = new self.ui = ui def rename(self, dir_): """Renames files in the directory tree""" print "Walking..." for dirpath, dirnames, filenames in os.walk(dir_): for filename in filenames: new_name = filename.replace(self.old, self.new) if new_name != filename: try: #os.rename(join(dirpath, filename), join(dirpath, new_name)) self.ui.info("Renaming", join(dirpath, filename), "to", new_name) except OSError: self.ui.error("Unable to rename", join(dirpath, filename), "to", new_name) if new_dirpath != dirpath: try: new_dirpath = dirpath.replace(self.old, self.new) #os.rename(dirpath, new_dirpath) self.ui.info("Dir renaming", dirpath, "to", new_dirpath) except OSError: self.ui.error("Unable to rename", dirpath, "to", new_dirpath) renamer = Renamer(old="_", new=" ") renamer.rename("/Users/riko/Documents") Io personalmente non creerei una classe per il renamer di cui sopra. Lo lascerei come un unica funzione di una dozzina di righe. -- -enrico _______________________________________________ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python