Cosè una programmazione guidata dagli eventi buona e pulita in Python? Al momento sto sperimentando quello che viene chiamato ' Callback Hell ' e voglio sapere come farlo nel modo giusto.


Migliore risposta

Sulla base dei commenti sopra, ecco “una strategia generale. Ovviamente i dettagli contano molto, ovviamente .

Fondamentalmente avrai due parti.

L oggetto evento o “ editore” è responsabile mantenere un elenco di tutte le funzioni che dovrebbero essere chiamate quando si verifica un evento. Ha un metodo fire() che scorre su quellelenco e chiama a turno tutte le funzioni. Probabilmente dovrebbe anche avere metodi per la gestione dellelenco (non è più necessario rimuovere una funzione dallelenco).

I gestori o “ subscribers” sono funzioni che “chiamerai quando levento si verifica effettivamente. Lunico problema è che devi controllare la firma dei gestori in modo che levento possa chiamarli senza fare alcuna introspezione extra.

Ecco un esempio estremamente minimale:

class Event(object):

def \_\_init\_\_(self, *args):

self.handlers = set()

self.args = args

def add(self, fn):

self.handlers.add(fn)

def remove(self, fn):

self.handlers.remove(fn)

def \_\_call\_\_(self, *args):

"""fire the event -- uses \_\_call\_\_ so we can just invoke the object directly..."""

runtime\_args = self.args + args

for each\_handler in self.handlers:

each\_handler(*runtime\_args)

class ExampleObject(object):

"""publish start and stop events"""

def \_\_init\_\_(self):

self.start = Event("started")

self.stop = Event("stopped")

def example\_handler(*args):

""" reacts to an event"""

print "example handler fired", args

fred = ExampleObject()

fred.start.add(example\_handler)

fred.stop.add(example\_handler)

fred.start()

fred.stop("optional extra arg")

Questo dovrebbe produrre

example handler fired ("started",)

example handler fired ("stopped", "optional extra arg")

I principali problemi di gestione sono:

Gestione delle eccezioni. devi decidere se il gestore deve essere protetto dalle eccezioni o meno. In caso contrario il codice sopra è più o meno OK, ma se non vuoi che un abbonato cattivo abbandoni lintero programma devi decidere come affrontare uneccezione e se “annullare liscrizione” al gestore offensivo .

Gestione della memoria. Lesempio usa solo una funzione come gestore; a meno che tu non cancelli () la funzione che non devi gestisci la sua vita. Tuttavia, spesso vorrai avere oggetti richiamabili o funzioni membro come gestori / sottoscrittori. In tal caso, probabilmente è necessario utilizzare riferimenti deboli piuttosto che linsieme ingenuo usato nellesempio, altrimenti i gestori di eventi finiranno per mantenere in vita gli oggetti dopo che avrebbero dovuto essere esclusi dallambito e dovrebbero essere raccolti in modo garbage.

Metadati: lesempio include un po di metadati, la stringa che viene passata come Event() vengono dichiarati. La tua applicazione potrebbe richiedere più o meno di questo. Più metadati di solito significano più accoppiamento, il che non è lideale. Tuttavia, se i tuoi gestori hanno tutti la firma (*args, **kwargs) puoi sempre passare i dati e poi decidere a livello di gestore se ti interessa o meno.

Buon riferimento : The Observer Pattern in Python

Esempio dellidea di base in azione: theodox / mGui

Risposta

Se vai al sito web del framework web tornado, hanno una pagina di esempi. In quella pagina cè un esempio di codice dellapplicazione di chat. È incredibilmente breve e comprensibile.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *