Hvad er god og ren begivenhedsdrevet programmering i Python? Jeg oplever i øjeblikket det, der hedder ' Callback Hell ' og vil vide, hvordan man gør det rigtigt.


Bedste svar

Baseret på kommentarerne ovenfor er her en generel strategi. Det er klart, at detaljerne betyder meget, selvfølgelig .

Dybest set vil du have to dele.

begivenhedsobjektet eller “ udgiver” er ansvarlig for vedligeholdelse af en liste over alle de funktioner, der skal kaldes, når en begivenhed sker. Den har en fire() -metode, der løber over denne liste og kalder alle funktionerne igen. Det burde sandsynligvis også have metoder til styring af listen (fjernelse af en funktion fra listen, det er ikke nødvendigt).

Handlerne eller “ abonnenter” er funktioner, som du vil ringe til, når begivenheden rent faktisk sker. Den eneste vanskelige bit der er, at du skal kontrollere håndtererens signatur, så begivenheden kan ringe til dem uden at foretage nogen ekstra introspektion.

Her er et ultra 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 skulle producere

example handler fired ("started",)

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

De vigtigste ledelsesproblemer er:

Undtagelseshåndtering. skal du beslutte, om føreren skal være undtagelsessikker eller ej. Hvis ikke ovennævnte kode er mere eller mindre OK, men hvis du ikke vil have en dårlig abonnent til at bringe hele programmet ned, skal du beslutte, hvordan du skal klare en undtagelse, og om du vil “fratrække” den krænkende handler .

Hukommelsesstyring. Eksemplet bruger kun en funktion som en handler, medmindre du sletter () den funktion, du ikke behøver administrere det “levetid. Men du vil ofte have enten objekter, der kan kaldes eller medlem funktioner som håndterere / abonnenter. Hvis det er tilfældet, er du sandsynligvis nødt til at bruge svage referencer i stedet for det naive sæt, der blev brugt i eksemplet – ellers vil eventhåndtererne ende med at holde genstande i live, efter at de burde være faldet uden for anvendelsesområdet og skulle indsamles skrald.

Metadata: Eksemplet inkluderer en lille smule metadata – den streng, der bliver sendt ind som Event() s erklæres. Din ansøgning har muligvis brug for mere eller mindre end dette. Flere metadata betyder normalt mere kobling, hvilket ikke er ideelt. Men hvis dine handlere alle har (*args, **kwargs) signaturen, kan du altid videregive dataene og derefter beslutte på handlerniveauet, om du er interesseret i det eller ej.

God reference : Observatørmønsteret i Python

Eksempel på den grundlæggende idé i aktion: theodox / mGui

Svar

Hvis du går til tornado web framework website, har de en eksempelside. På denne side er der et eksempel på chatapplikationskode. Det er fejlagtigt kort og forståeligt.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *