[Tutor] Java Observer/Observable type module in Python

D-Man dsh8290@rit.edu
Mon, 26 Feb 2001 13:39:30 -0500


On Tue, Feb 27, 2001 at 06:51:01AM +1300, Phil Bertram wrote:
| Hi all
| 
| I was reading some Java info and came across  the Observer and Observable
| classes which appear to work together to communicate changes in an object's
| state to one or many other objects.
| 
| Is there a similar feature in Python ?

This can be done with (almost) any language.  The Observer pattern
actually comes from "Design Patterns" by the Gang of Four, with the
example being in C++.  (or Smalltalk, they used both languages in the
book)



class Observer :
    def changed( self , observable ) :
        print "%s has changed" % str( observable )

class Observable :
    def __init__( self , init_value ) :
        self.observers = []
        self.value = init_value

    def __str__( self ) :
        return "Observable %d : %s" % id( self ) , self.value

    def add_observer( self , observer ) :
        self.observers.append( observer )

    def remove_observer( self , observer ) :
        self.observer.remove( observer )

    def _notify_of_change( self ) :
        for observer in self.observers :
            observer.changed( self )

    def mutator_function_that_changes_self( self , new_value ) :
        self.value = new_value
        self._notify_of_change()


# test my code :
if __name__ == "__main__" :
    observer1 = Observer()
    observer2 = Observer()
    observable = Observable( 13 )
    observable.add_observer( observer1 )
    observable.add_observer( observer2 )

    observable.mutator_function_that_changes_self( 50 )

    observable.remove_observer( observer1 )

    observable.mutator_function_that_changes_self( 20 )

    observable.remove_observer( observer2 )




BTW,  I just wrote this and haven't tested it so if something looks
ridiculously stupid, I probably made a mistake.  Also, instead of
using a list in the Observable class, a dictionary could be used to
improve performance on adding/removing observers.  This would require
that the observers be hashable.  Using a list like this makes the
order the observers recieve notification the same as the order they
registered themselves.  A dictionary wouldn't allow this.


Java provides classes/interfaces in the standard library called
Observer and Observable that implement this pattern in a very basic
way.  The main need for this in Java is its static type checking and
inablility to pass function "pointers" (pointers in C/C++, objects in
Python) so the Observable must know the name of the method to call in
the Observer.  AFIAK Swing doesn't use those classes (maybe part of
the implementation, I don't know) but it uses the Observer Pattern
heavily.  Since you are using Python, you can just create the
Observer/Observable interfaces you need when you need them and make
the suitable for that particular task, rather than trying to make a
generalized implementation.  Also, you could choose to accept a
function object in the add_observer function, instead of an Observer
object allowing clients to determine exactly which function will get
the notification.  (A la gtk--, the C++ bindings for the GTK+ toolkit)
This is my preferred mechanism for listening for GUI events.


HTH,
-D