Cel mai bun răspuns
Pe baza comentariilor de mai sus, aici este o strategie generală. Evident, detaliile contează foarte mult, desigur .
Practic veți avea două părți.
obiectul eveniment sau „ editor” este responsabil pentru menținerea unei liste cu toate funcțiile care ar trebui apelate atunci când se întâmplă un eveniment. Are o metodă fire()
care trece peste lista respectivă și apelează pe rând toate funcțiile. Probabil ar trebui, de asemenea, să aibă metode de gestionare a listei (eliminarea unei funcții din listă nu mai este necesară).
Handlerele sau „ abonați” sunt funcții pe care le veți apela atunci când evenimentul se va întâmpla efectiv. Singurul aspect complicat este că trebuie să controlați semnătura handlerilor, astfel încât evenimentul să le poată apela fără a face nicio introspecție suplimentară.
Iată un exemplu extrem de minim:
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")
Aceasta ar trebui să producă
example handler fired ("started",)
example handler fired ("stopped", "optional extra arg")
Principalele probleme de gestionare sunt:
Tratarea excepțiilor. trebuie să decideți dacă gestionarul trebuie să fie sau nu în condiții de siguranță. Dacă nu, codul de mai sus este mai mult sau mai puțin OK, dar dacă nu doriți ca un abonat rău să aducă în jos întregul program, trebuie să decideți cum să faceți față unei excepții și dacă să „dezabonați” sau nu administratorul care a încălcat .
Managementul memoriei. Exemplul folosește doar o funcție ca handler; dacă nu eliminați () funcția pe care nu trebuie să o gestionează-l pe toată durata vieții. Cu toate acestea, veți dori adesea să aveți fie obiecte apelabile, fie funcții de membru ca handler / abonați. Dacă da, probabil că trebuie să utilizați referințe slabe, mai degrabă decât setul naiv folosit în exemplu – în caz contrar, gestionarii de evenimente vor ajunge să păstreze obiectele în viață după ce ar fi trebuit să fi ieșit din sfera de aplicare și ar trebui să fie colectate la gunoi.
Metadate: Exemplul include un pic de metadate – șirul care este transmis ca Event()
s sunt declarate. Aplicația dvs. ar putea avea nevoie de mai mult sau mai puțin decât aceasta. Mai multe metadate înseamnă de obicei mai multe cuplări, ceea ce nu este ideal. Cu toate acestea, dacă gestionarele dvs. au toate semnătura (*args, **kwargs)
puteți transmite oricând datele și apoi puteți decide la nivel de gestionare dacă vă pasă sau nu.
Bună referință : Modelul de observator din Python
Exemplu al ideii de bază în acțiune: theodox / mGui
Răspuns
Dacă accesați site-ul web tornado web framework, acestea au o pagină de exemple. Pe pagina respectivă există un exemplu de cod de aplicație de chat. Este foarte scurt și ușor de înțeles.