Idee für ein Eventsystem...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

bislang habe ich nach verschiedenen Ereignissen einfach Instanzen von

Code: Alles auswählen

class Event(object):
    #irgendwann mal von BlackJack bekommen...
    def __init__(self):
        self.callbacks = set()
   
    def __call__(self, *args, **kwargs):
        for callback in self.callbacks:
            callback(*args, **kwargs)
   
    def add(self, listener):
        self.callbacks.add(listener)
   
    def remove(self, listener):
        self.callbacks.remove(listener)
aufgerufen. Das wird mir jetzt aber etwas zu unflexibel und zu unübersichtlich.

Ich habe mir daher überlegt, 'Event()' folgendermaßen umzubauen:
1. Ein potentieller Event wird angemeldet, z. B. 'APP_CHANGE' und mit callback(s) verbunden.
2. 'Event()' erhält eine Methode 'trigger', die ich dann an verschiedenste Exemplare weitergebe.
3. Wird z. B. in der Klasse 'Appointment()' ein Termineintrag geändert, wird über 'trigger' samt Parameter 'APP_CHANGE' die/der dazugehörige(n) callback(s) aufgerufen.

Code: Alles auswählen

class Event(object):
    def __init__(self):
        self.events = {}
   
    def new_(self, name, listener):
        self.events[name] = set([listener])

    def add(self, name, listener):
        self.events[name].add(listener)
   
    def remove(self, name, listener):
        self.events[name].remove(listener)
   
    def trigger(self, name, *args, **kwargs):
        for callback in self.events[name]:
            callback(*args, **kwargs)
Was ist davon zu halten?
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich würde die in Python zur Verfügung stehenden Datentypen gar nicht so sehr "entfremden". Das, was du implementiert hast, könnte man doch sicher mit direkterem Zugriff über ein defaultdict lösen. Man müsste dann bloß noch das Verknüpfen der `Listener()` mit den Ereignissen (wo eben das `defaultdict` zum Einsatz kommen kann) von dem eigentlichen Eventhandling (`trigger()`) trennen. Bist du eigentlich sicher, dass du `Listener()` hast und nicht eher `Handler()`? Also, ich weiß ja nicht, was sich bei dir hinter den "Dingern" (vermutlich Klassen) verbirgt...
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Blinker kennst du schon?
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@DasIch:
Nein, Blinker kannte ich noch nicht. Schaut so aus, als ob das was für mich wäre. Bevor ich das allerdings beurteilen kann, muss ich mich wohl noch tiefer in die Materie reinarbeiten...
snafu hat geschrieben:Das, was du implementiert hast, könnte man doch sicher mit direkterem Zugriff über ein defaultdict lösen.
Meinst Du damit sowas?

Code: Alles auswählen

class Event(object):
    def __init__(self):
        self.callbacks = set()
   
    def __call__(self, *args, **kwargs):
        for callback in callbacks:
            callback(*args, **kwargs)

    def add(self, handler):
        self.callbacks.add(handler)

def update(content):
    print content

Code: Alles auswählen

In [20]: d = collections.defaultdict(Event.add)

In [21]: d['UPDATE'] = update

In [22]: d['UPDATE']('Alles neu macht der Mai!')
Alles neu macht der Mai!
Vorausgesetzt, das ist so richtig: Wie setze ich so ein dictionary konkret ein? Etwa so?

Code: Alles auswählen

class Content(object):
    def __init__(self):
        pass

    def update(self, data):
        #do something with data...
        return 'UPDATE'

Code: Alles auswählen

In [38]: c = Content()

In [39]: data = 'blabla'

In [40]: d[c.update(data)](data)
blabla
snafu hat geschrieben:Bist du eigentlich sicher, dass du `Listener()` hast und nicht eher `Handler()`?
Ich hab' das noch nicht wirklich verinnerlicht, darum bringe ich solche Begriffe gerne durcheinander... :oops:
Im obigen defaultdict-Beispiel gibt es keine listener und die Funktion 'update()' ist ein handler. Ist das so richtig? Und wie nennt man dabei das defaultdict 'd'?

Ist die Namensgebung in meinem nächsten Beispiel richtig?

Code: Alles auswählen

class Listener(object):
    def __init__(self, publisher):
        publisher.add(self.update)

    def update(self, content):
        print content

class Publisher(object):
    def __init__(self):
        self._listener = set()

    def add(self, listener):
        self._listener.add(listener)

    def update(self, data):
        #do something with data...
        for listener in self._listener:
            listener(data)
Puh... nach meinem Geschmack dürfte der Groschen gerne etwas schneller fallen...

Danke für Eure Hilfe!!

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Antworten