How can I make a dictionary that marks itself when it's modified?

Michael Spencer mahs at
Thu Jan 12 13:59:39 EST 2006

sandravandale at wrote:
> It's important that I can read the contents of the dict without
> flagging it as modified, but I want it to set the flag the moment I add
> a new element or alter an existing one (the values in the dict are
> mutable), this is what makes it difficult. Because the values are
> mutable I don't think you can tell the difference between a read and a
> write without making some sort of wrapper around them.
> Still, I'd love to hear how you guys would do it.
> Thanks,
> -Sandra


You appear to want:

D = {"a":obj1, "b":obj2}

when obj1 or obj2 changes, to notify D

I think that's hard to do in the general case (i.e., for any value of obj).  You 
will have to design/modify obj1 and obj2 or wrap them it to achieve this.  If 
the objects are not homogeneous, I'd give up ;-)

If you can design obj for the purpose it shouldn't be do hard, using the 
observer pattern:

Here's a sketch:

class Observable(object):
     """An object that notifies observers when it is changed"""
     def __init__(self):
         self._observers = []
     def add_observer(self, observer):
     def _notify(self, attrname, newval):
         for observer in self._observers:
             observer.notify(self, attrname, newval)
     def __setattr__(self, attrname, val):
         object.__setattr__(self, attrname, val)
         self._notify(attrname, val)

class DictObserver(dict):
     """A dict that observes Observable instances"""
     def __setitem__(self, key, value):
         assert isinstance(value, Observable)
         dict.__setitem__(self, key, value)
     def notify(self, obj, attr, newval):
         print "%s.%s = %s" % (obj, attr, newval)

  >>> a = Observable()
  >>> b = Observable()
  >>> D = DictObserver()
  >>> D["a"] = a
  >>> D["b"] = b
  >>> a.new_attribute = 4
  <observer_dict.Observable object at 0x01AE9210>.new_attribute = 4
  >>> b.new_attribute = 6
  <observer_dict.Observable object at 0x01AE98F0>.new_attribute = 6
  >>> a.new_attribute = 5
  <observer_dict.Observable object at 0x01AE9210>.new_attribute = 5


More information about the Python-list mailing list