text: 
  class Observable(object):
  
      def __init__(self, **kwargs):
          super(Observable, self).__init__(**kwargs)
          self._observers = set()
          self.notify_observers()
  
      def register_observer(self, observer):
          if not issubclass(observer.__class__, Observer):
              raise TypeError()
          self._observers.add(observer)
          observer.notify()
  
      def unregister_observer(self, observer):
          self._observers.remove(observer)
  
      def notify_observers(self):
          for observer in self._observers:
              observer.notify()
  
  
  class IterObservable(Observable):
      """Observable that auto-notifies observers if indexed assignment is performed on it."""
  
      def __setitem__(self, key, value):
          self.notify_observers()
  
  
  class Observer(object):
  
      def __init__(self, **kwargs):
          super(Observer, self).__init__(**kwargs)
          # self._requires_update = True
  
      def notify(self):
          """Flags Observer to perform update() at proper time."""
          # self._requires_update = True
          try:
              self.update()
          except AttributeError:
              pass
  
      def on_change(self):
          """Callback for if change  detected. Meant to be overridable by subclasses."""
          pass
  
      def update(self):
          # """Check if any updates happened. If not, return False.  Else, perform callback and reset update flag, and return True."""
          self.on_change()
  
  
  
  class AutoRegisterObserver(Observer):
      # Auto-checks if new attributes are Observable. If so, registers self with them and notifies a change.
  
      def __setattr__(self, key, value):
          super(AutoRegisterObserver, self).__setattr__(key, value)
          if issubclass(value.__class__, Observable):
              value.register_observer(self)