Co je dobré a čisté programování založené na událostech v Pythonu? V současné době zažívám to, čemu se říká „Callback Hell“. a chcete vědět, jak to udělat správně.


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ý.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *