On Sun, Mar 08 2015, Alessandro Re wrote: > Ciao Marco, > > intanto grazie per la risposta :)
Non c'è di che :) > 2015-03-08 7:54 GMT+00:00 Marco Giusti <marco.giu...@posteo.de>: > > Come registri le callback? Gli oggetti in python sono referenziati da > > del codice python o solo dalle callback di c++? In questo caso basta > > che, nel momento in cui distruggi l'oggetto C, deregistri le callback > > e riduci il numero di referenze del metodo. Se i metodi di un oggetto > > P sono usati come callback di un solo oggetto C, al momento che > > tu rilasci tutte le callback non esistono più riferimenti all'oggetto > > python. > > Il problema è proprio la registrazione delle callback... Per ora ho un > meccanismo piuttosto primitivo: > quando un evento accade, viene chiamato un metodo on_evento(*args) di python. > L'idea è che l'oggetto tiene una lista di callback da > chiamare per quell'evento, e quel metodo è definito più o meno come > > def on_evento(self, *args): > for callback in self._callbacks: > callback(*args) > > Però è per l'appunto primitivo, e non viene assolutamente gestita la > rimozione delle callback. Prima di avventurarmi ed inventare qualcosa > che cerchi di automatizzare la rimozione, volevo capire se c'era già > qualche pattern usato in questi casi. Il patter che più gli assomigli è l'Observer ma non sono sicuro che la terminologia sia quella giusta in questo caso. Comunque l'implementazione è all'incirca quella: ... self._events = {} def register(self, event, callback): self._events.setdefault(event, []).append(callback) def unregister(self, event, callback): callbacks = self._events[event] callbacks.pop(callbacks.index(callback)) def on_event(self, event, *args): for callback in self._events[event]: callback(*args) Così come registri una callback, così la rimuovi. Se non riesci a definire formalmente un ciclo di vita per i tuoi oggetti, allora è probabile che nel tuo design qualcosa sia sbagliato. Ancora una volta ti offro una soluzione semplicistica. Se l'oggetto prima di essere distrutto scatena l'evento "on_remove": def on_remove(self, *args): self.on_event("remove", *args) del self._events.clear() def use(...): obj = Object(...) event_handler.register("foo", obj.foo) event_handler.register("remove", obj.remove) event_handler.register("foo", Object(...).foo) in questa maniera le uniche referenze ai due oggetti "Object" sono nell'event_handler. Prima che l'oggetto C++ venga distrutto scatena l'evento "on_remove" e le referenze dei due oggetti "Object" vengono riportate a zero. Fossi in te inizierei con una implementazione di questo tipo. Se è vero che è primitiva, le specifiche non sembrano ancora definite e trovo inutile andare a complicarsi troppo la vita. Scrivi un paio di test, vedi se il codice che viene fuori è soddisfacente o se richiede qualche hack non troppo elegante e parti da lì per migliorarlo. > >> Come posso rendere sincrona (bloccante) l'invocazione di un comando? > > > > La prima idea che mi viene in mente è di infilare la callback dentro la > > send e di chiamare sleep per salvare qualche ciclo macchina: > > > > def send_data_blocking(data): > > def go(): > > free_to_go = True > > free_to_go = False > > send_data(data, callback=go) > > while not free_to_go: > > sleep(0.1) > > Grazie, proverò con la sleep :) (btw, in go() non ci andrebbe un > "nonlocal free_to_go"?) Per un momento ho creduto che "go" fosse il linguaggio. Non conosco nonlocal ma hai ragione se dici che c'è un errore grossolano. Più o meno è questo che avevo in mente, ma non avendo neanche provato il codice... def send_data_blocking(data): def go(): free_to_go[0] = True free_to_go = [False] send_data(data, callback=go) while not free_to_go[0]: sleep(0.1) Ciao m. _______________________________________________ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python