Hva er god og ren hendelsesdrevet programmering i Python? Jeg opplever for øyeblikket det som heter ' Callback Hell ' og vil vite hvordan du gjør det riktig.


Beste svaret

Basert på kommentarene ovenfor, her er en generell strategi. Det er klart at detaljene betyr mye, selvfølgelig .

I utgangspunktet vil du ha to deler.

hendelsesobjektet eller « utgiveren» er ansvarlig for opprettholde en liste over alle funksjonene som skal kalles når en hendelse skjer. Den har en fire() -metode som sløyfer over den listen og kaller alle funksjonene etter tur. Det burde sannsynligvis også ha metoder for å administrere listen (fjerne en funksjon fra listen den er ikke nødvendig).

håndtererne eller « abonnenter» er funksjoner du kommer til å ringe når hendelsen faktisk skjer. Den eneste vanskelige biten der er at du trenger å kontrollere håndtererens signatur slik at arrangementet kan ringe dem uten å gjøre noe ekstra introspeksjon.

Her er et ekstremt minimalt eksempel:

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

Det burde produsere

example handler fired ("started",)

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

Hovedadministrasjonsproblemene er:

Unntakshåndtering. du må bestemme om føreren må være unntaksikker eller ikke. Hvis ikke den ovennevnte koden er mer eller mindre OK, men hvis du ikke vil at en dårlig abonnent skal få ned hele programmet, må du bestemme hvordan du skal takle et unntak, og om du vil «fjerne abonnementet» på den krenkende håndtereren. .

Minnehåndtering. Eksemplet bruker bare en funksjon som behandler, med mindre du sletter () funksjonen du ikke trenger å administrere det «levetid. Men du vil ofte ha enten objekter som kan kalles eller medlemsfunksjoner som håndterere / abonnenter. I så fall må du sannsynligvis bruke svake referanser i stedet for det naive settet som ble brukt i eksemplet – ellers vil hendelsesbehandlerne ende opp med å holde gjenstander i live etter at de burde ha falt utenfor omfanget og burde samle søppel.

Metadata: Eksemplet inkluderer litt metadata – strengen som blir sendt inn som Event() er erklært. Søknaden din kan trenge mer eller mindre enn dette. Flere metadata betyr vanligvis mer kobling, noe som ikke er ideelt. Men hvis håndtererne dine alle har (*args, **kwargs) signaturen, kan du alltid sende dataene og deretter bestemme på behandlernivå om du bryr deg om det eller ikke.

God referanse : Observatørmønsteret i Python

Eksempel på grunnideen i aksjon: theodox / mGui

Svar

Hvis du går til tornado web framework website, har de en eksempelside. På den siden er det et eksempel på en chat-applikasjonskode. Det er feil og forståelig.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *