Mi a jó és tiszta eseményvezérelt programozás a Pythonban? Jelenleg az úgynevezett ' visszahívási pokol ' és szeretnék tudni, hogyan kell jól csinálni.


Legjobb válasz

A fenti megjegyzések alapján itt az általános stratégia. Természetesen a részletek természetesen sokat számítanak .

Alapvetően két részből áll.

A eseményobjektum vagy a “ megjelenítő” felelős azoknak a funkcióknak a listája, amelyeket meg kell hívni, amikor egy esemény bekövetkezik. Van egy fire() metódusa, amely hurokba lép a listán, és az összes függvényt egymás után hívja meg. Valószínűleg rendelkeznie kell módszerekkel a lista kezelésére (egy olyan funkció eltávolítása a listából, amelyre már nincs szükség).

A kezelők vagy a “ előfizetők” olyan funkciók, amelyeket akkor fogsz hívni, amikor az esemény valóban megtörténik. Az egyetlen trükkös dolog az, hogy ellenőriznie kell a kezelők aláírását, hogy az esemény minden további önvizsgálat nélkül felhívhassa őket.

Itt egy nagyon minimális példa:

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")

Ennek létre kell hoznia

example handler fired ("started",)

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

A fő kezelési problémák a következők:

Kivételek kezelése. el kell döntenie, hogy a kezelőnek kivételesen biztonságosnak kell-e lennie vagy sem. Ha nem, akkor a fenti kód nagyjából rendben van, de ha nem akarja, hogy egy rossz előfizető lerombolja az egész programot, akkor el kell döntenie, hogyan kell kezelni a kivételt, és hogy “el kell-e iratkozni” a vétkes kezelőről. .

kezelje az élettartamát. Azonban gyakran azt szeretné, hogy hívható objektumok vagy tagfunkciók legyenek kezelőként / előfizetőként. Ha igen, akkor valószínűleg gyenge referenciákat kell használnia a példában használt naiv halmaz helyett – különben az eseménykezelők végül életben tartják az objektumokat, miután ki kellett volna esniük a hatókörből, és szemetet kell gyűjteniük.

Metaadatok: A példa tartalmaz egy kis metaadatot – a karakterláncot, amelyet Event() s vannak deklarálva. Alkalmazásához ennél többre vagy kevesebbre lehet szükség. A több metaadat általában több összekapcsolást jelent, ami nem ideális. Ha azonban az összes kezelője rendelkezik a (*args, **kwargs) aláírással, akkor mindig átadhatja az adatokat, majd a kezelő szintjén eldöntheti, hogy törődik-e velük vagy sem.

Jó referencia : A megfigyelő minta a Pythonban

Példa az alapötletre a műveletben: theodox / mGui

Válasz

Ha felkeresi a tornádó webes keretrendszer webhelyét, van egy példa oldaluk. Ezen az oldalon található egy példa a csevegőalkalmazás kódjára. Ez hibásan rövid és érthető.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük