Nejlepší odpověď
Na základě výše uvedených komentářů je zde obecná strategie. Na detailech samozřejmě samozřejmě záleží hodně .
V zásadě budete mít dvě části.
objekt události nebo „ vydavatel“ odpovídá za udržování seznamu všech funkcí, které by měly být vyvolány, když dojde k události. Má metodu fire()
, která se nad tímto seznamem smyčí a postupně volá všechny funkce. Pravděpodobně by také měl mít metody pro správu seznamu (odstranění funkce ze seznamu, není to potřeba).
Obslužné rutiny nebo „ odběratelé“ jsou funkce, kterým zavoláte, když k události skutečně dojde. Jediným záludným kouskem je, že musíte ovládat podpis obslužných rutin, aby je událost mohla volat, aniž by prováděla jakoukoli další introspekci.
Zde je velmi minimální příklad:
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")
To by mělo vytvořit
example handler fired ("started",)
example handler fired ("stopped", "optional extra arg")
Hlavní problémy se správou jsou:
Zpracování výjimek. musíte se rozhodnout, zda obslužný program musí být bezpečný pro výjimky nebo ne. Pokud tomu tak není, výše uvedený kód je víceméně v pořádku, ale pokud si nepřejete, aby špatný odběratel zničil celý program, musíte se rozhodnout, jak se vyrovnat s výjimkou a zda „odhlásit“ odsuzujícího obsluhu .
Správa paměti. Příklad používá pouze funkci jako obslužnou rutinu; pokud nevymažete () funkci, kterou nemusíte spravovat jeho životnost. Často však budete chtít mít jako obslužné / odběratelné objekty buď volané objekty, nebo členské funkce. Pokud ano, pravděpodobně budete muset použít spíše slabé odkazy než naivní sadu použitou v příkladu – jinak obslužné rutiny událostí nakonec udrží objekty naživu poté, co by měly vypadnout z rozsahu a měly by být shromažďovány odpadky.
Metadata: Příklad obsahuje trochu metadat – řetězec, který se předává jako Event()
s jsou deklarovány. Vaše aplikace možná bude potřebovat více či méně. Více metadat obvykle znamená více propojení, což není ideální. Pokud však všichni vaši manipulační pracovníci mají podpis (*args, **kwargs)
, můžete data vždy předat a poté se rozhodnout na úrovni obslužné rutiny, jestli vám na tom záleží, nebo ne.
Dobrá reference : The Observer Pattern in Python
Příklad základní myšlenky v akci: theodox / mGui
Odpovědět
Pokud přejdete na webovou stránku tornádo webového rámce, mají stránku s příklady. Na této stránce je ukázkový kód aplikace chatu. Je neúspěšně krátký a srozumitelný.