On Tue, Mar 10 2015, Alessandro Re wrote: > 2015-03-10 17:33 GMT+00:00 Marco Giusti <marco.giu...@posteo.de>: > > Credo che puoi fare meglio che questo. Vuoi che ogni callback venga > > invocata una sola volta? > > Ah sì, che si possa far meglio è fuori di dubbio :D Comunque no, non > voglio che *ogni* callback venga invocata una sola volta. > Ma comunque ammetto che avrei potuto trovare una soluzione molto più > pulita. > > > Inoltre passare un oggetto come primo argomento mi suona tanto da > > antipattern. Non è sbagliato, ma chiediti che oggetto sia. Mi suona da > > antipattern per come i metodi e le funzioni in python funzionano. > > > come vedi le due chiamate sono identiche ma in più il metodo riceve > > un oggetto (su cui opera il metodo). Il tuo codice sembra reinventare > > una ruota che ormai è ben collaudata. > > Ok, premetto che mi è chiaro l'esempio che fai, e ci ho pensato un po' > su queste tue parole, ma non credo di aver capito cosa intendi; ti > spiace argomentare un pochino?
Ti posto un po' di codice perché credo di essere più chiaro e conciso con qualche linea di codice che con le parole: class System(object): def __init__(self, name): self.name = name def ping(self, arg): return "{}: {}".format(self.name, arg) class Foo(object): def __init__(self, system): self.system = system def foo(self, arg): print self.system.ping(arg) def bar(arg): print "bar", arg class Registry(object): def __init__(self): self.events = {} def register(self, event, callback): self.events.setdefault(event, []).append(callback) def unregister(self, event, callback): self.events[event].remove(callback) def fire_event(self, event, arg): for callback in self.events[event]: callback(arg) registry = Registry() foo1 = Foo(System("Mercury")) foo2 = Foo(System("Venus")) registry.register("ping", foo1.foo) registry.register("ping", bar) registry.register("ping", foo2.foo) registry.register("ping", bar) registry.fire_event("ping", "hallo") print "=" * 20 registry.unregister("ping", foo1.foo) registry.unregister("ping", bar) registry.fire_event("ping", "hallo") come vedi funzioni e metodi vengono usati indistintamente ma i metodi, a differenza delle funzioni, ricevono un argomento in più: self. Tuoi puoi gestire questo a tua convenienza. Per esempio puoi creare un oggetto "Foo" con funzione di adapter per un più generico oggetto "System". L'implementazione della classe "Registry" risulta molto più pulita. > > Comunque l'ultima parola l'hai tu perché il codice che hai postato non > > ci aiuta molto a capire esattamente il funzionamento di questi > > fantomatici oggetti C++. > > No, ecco, la questione C++ l'avete ingrandita un po' voi :P Nel senso > che sì, io ho degli oggetti C++ sottostanti, ma il punto che volevo > fare è solo che voglio che non esistano oggetti python che facciano > riferimento ad oggetti C++ ormai distrutti... C++ l'ho nominato solo > per giustificare il fatto che gli oggetti python, dopo la remove(), > dovrebbero essere cancellati ovunque. Tutto qua :) > > L'unica cosa che ho omesso è che, in remove(), oltre a chiamare le > callback, io ho anche una chiamata tipo > `self._oggetto_cpp.distruggi()` e se dopo di essa provo a fare > `self._oggetto_cpp.metodo()` ottengo un bel errore :) E' possibile, ma è l'esatta interazione degli oggetti che mi sfugge e "no code no party". Quando l'oggetto C++ (C) viene distrutto emette un evento (E) ed è l'oggetto python (P) che lo distrugge esplicitamente? In casi come questo trovo molto utile scrivere, io lo faccio a mano con carta e penna, un diagramma degli stati. In questo specifico caso opterei per creare uno stato intermedio e gli darei un nome altisonante come walking_dead, dove l'oggetto è ancora disponibile per gestire gli ultimi eventi, ma verrà distrutto alla fine di questi. class Handler: def __init__(self, cplusplus): self.__c = cplusplus self.__cb = {"remove": []} def remove(self): self.__c.remove() # emette l'ultimo evento prima di morire def on_remove(self, *args): for callback in self.__cb["remove"]: callback(*args) self.__cb.clear() self.__c = None Questo però implica che l'unico metodo chiamato esternamente sia "remove". Che "self._oggetto_cpp.metodo()" lanci un errore se prima è stato chiamato "self._oggetto_cpp.distruggi()" è cosa buona e giusta e il problema è a valle, non a monte. Ciao m. _______________________________________________ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python