Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Observer is one of the patterns I find myself using over and again, but until recently I never felt completely happy with my Python implementations of it.

You have two classes, the subject and an observer which registers itself with the subject and receives notification callbacks when data changes in the subject. I find the GoF form of this pattern somewhat limiting, because they describe a system where a subject class has a general 'notify' method used for everything (although they do suggest a mechanism for generating more selective events using aspects).

The implementation described here uses a more general, and I believe cleaner form of event generation which is based (loosely) on the event structure from Microsoft's .Net framework. It is best described starting with the intended use.

The actual example is taken from the GoF book, although of course the implementation is not. ClockTimer is a subject for storing and maintaining the time of day. It notifies its Observers every second. ClockTimer provides the interface for retrieving individual time units such as the hour, minute and second:

class ClockTimer: def GetHour(self): return self._hour def GetMinute(self): return self._minute def GetSecond(self): return self._second TickEvent = Event() def OnTick(self): ClockTimer.TickEvent.call(self, self.GetHour(), self.GetMinute(), self.GetSecond()) def Tick(self): # update internal time-keeping state # ... self.OnTick()

The Tick method gets called by an internal timer at regular intervals. It updates the internal state and calls the OnTick method to notify observers of the change.

The OnTick method fires the event with whatever parameters seem appropriate. Firing the event indirectly in this way allows subclasses to override the event handling.

Although we have a single Event in this class, the implementation allows for any number of different events to be defined.

Now, we can define a class DigitalClock that displays the time:

class DigitalClock(Widget): def __init__(self, clockTimer): self.__subject = clockTimer clockTimer.TickEvent += self.Update def close(self): self.__subject.TickEvent -= self.Update def Update(self, subject, hour, min, sec): self.displayedTime = (hour, min, sec) self.Draw() def Draw(self): # draw the digital clock

N.B. We need an explicit close method to be called on this object because there is a circular dependency (ClockTimer contains a reference to the UpdateMethod of the DigitalClock instance, and the DigitalClock instance stores a reference to the clockTimer). This means that a __del__ method would never be called. In cases where this could be a problem, one solution would be to define a WeakMethod class that simulates a bound method but only holds a weak reference to the instance.

The plumbing that allows this to work is as follows:

class Delegate: '''Handles a list of methods and functions Usage: d = Delegate() d += function # Add function to end of delegate list d(*args, **kw) # Call all functions, returns a list of results d -= function # Removes last matching function from list d -= object # Removes all methods of object from list ''' def __init__(self): self.__delegates = [] def __iadd__(self, callback): self.__delegates.append(callback) return self def __isub__(self, callback): # If callback is a class instance, # remove all callbacks for that instance self.__delegates = [ cb for cb in self.__delegates if getattr(cb, 'im_self', None) != callback] # If callback is callable, remove the last # matching callback if callable(callback): for i in range(len(self.__delegates)-1, -1, -1): if self.__delegates[i] == callback: del self.__delegates[i] return self return self def __call__(self, *args, **kw): return [ callback(*args, **kw) for callback in self.__delegates]

The delegate class maintains a list of callbacks (so we can have several observers for a single subject). The only operations supported on a delegate are to add a function, remove a function or call all of the functions in the delegate. The callback functions are stored in order (so first added is also first called), and removed in last in/first out order.

We could create the Delegate instances in __init__, but there is a potential drawback to this. If we created a class that could fire many events, but events mostly went unused, we should have a lot of delegates created for no reason. The Event class below creates delegates only when they are needed, and the indirect call used in the subject class supports this:

class Event(property): '''Class event notifier Usage: class C: TheEvent = Event() def OnTheEvent(self): self.TheEvent(self, context) instance = C() instance.TheEvent += callback instance.OnTheEvent() instance.TheEvent -= callback ''' def __init__(self): self.attrName = attrName = "__Event_" + str(id(self)) def getEvent(subject): if not hasattr(subject, attrName): setattr(subject, attrName, Delegate()) return getattr(subject, attrName) super(Event, self).__init__(getEvent) def call(self, subject, *args, **kw): if hasattr(subject, self.attrName): getattr(subject, self.attrName)(subject, *args, **kw)

Within the ClockTimer class a reference to instance.TickEvent will create the Delegate. The Delegate could be called using self.TickEvent(args), but this would always create it. By calling it instead using ClockTimer.TickEvent.call(args) we avoid doing this unneccessarily.