"Signals and slots are used for communication between objects. The signals and slots mechanism is a central feature of Qt and probably the part that differs most from the features provided by other frameworks". I literally copied that off from the QT Signals and Slots documentation. Until recently I didn't really use signal and slots much in my python code. I knew about them but did not really see the need. Until I started using QT and realized how great they are at decoupling my classes.
Below is an implemntation that I use a lot.
from __future__ import print_function import inspect from weakref import WeakSet, WeakKeyDictionary class Signal(object): def __init__(self): self._functions = WeakSet() self._methods = WeakKeyDictionary() def __call__(self, *args, **kargs): # Call handler functions for func in self._functions: func(*args, **kargs) # Call handler methods for obj, funcs in self._methods.items(): for func in funcs: func(obj, *args, **kargs) def connect(self, slot): if inspect.ismethod(slot): if slot.__self__ not in self._methods: self._methods[slot.__self__] = set() self._methods[slot.__self__].add(slot.__func__) else: self._functions.add(slot) def disconnect(self, slot): if inspect.ismethod(slot): if slot.__self__ in self._methods: self._methods[slot.__self__].remove(slot.__func__) else: if slot in self._functions: self._functions.remove(slot) def clear(self): self._functions.clear() self._methods.clear() class Emitter(object): def __init__(self): self.changed= Signal() self.second_value_changed = Signal() self.value = None def set_value(self, value): self.changed(value) def set_second_value(self, value): self.second_valued_changed() class Reciever(object): def emitter_updated(self, *args, **kwargs): print("Signal recieved") print(*args) print(**args) e = Emitter() r = Reciever() e.changed.connect(r.emitter_updated)
The "Emitter" class is an example of a class that will send a message whenever "value" is changed.
The "Receiver" class has a method called "emitter_updated". This receives the signal whenever "value" is changed in the "Emitter" class.
The code snippet shows the Emitter and the Receiver class know nothing about each other. When we create an instance , we "connect" them as follows:
e = Emitter() r = Reciever() e.changed.connect(r.emitter_updated)