Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Property Change Listener Pattern

Tags:

python

Anyone know of any easy way to track changes to a dictionary object in python? I am at a high level doing crud, so I have a couple methods that handle changing a dictionary, if the dictionary changes I want to call a function to basically do an Observer/Notify.

 class MyClass(object):
     def update(self, item):
        changed = False

        if(self.my_dict.has_key(item.id)):
           self.my_dict[item.id] = item
           changed = True

        if(changed):
          self.notify()

What I am trying to avoid is all of the tracking(setting the boolean) code. Was hoping there was an easier way to track changes. This is a simple case, but there could have been more complicated logic that would result in me having to set the changed flag.

like image 522
Nix Avatar asked Mar 03 '11 21:03

Nix


2 Answers

You can derive from the dict class and add a callback on any changes. This requires to overwrite any methods that change the dictionary:

class NotifyDict(dict):
    __slots__ = ["callback"]
    def __init__(self, callback, *args, **kwargs):
        self.callback = callback
        dict.__init__(self, *args, **kwargs)
    def _wrap(method):
        def wrapper(self, *args, **kwargs):
            result = method(self, *args, **kwargs)
            self.callback()
            return result
        return wrapper
    __delitem__ = _wrap(dict.__delitem__)
    __setitem__ = _wrap(dict.__setitem__)
    clear = _wrap(dict.clear)
    pop = _wrap(dict.pop)
    popitem = _wrap(dict.popitem)
    setdefault = _wrap(dict.setdefault)
    update =  _wrap(dict.update)
like image 73
Sven Marnach Avatar answered Sep 19 '22 14:09

Sven Marnach


Subclass dict and override __setitem__, making sure to call dict.__setitem__ after your stuff to ensure the item actually gets saved.

class Notifier(dict):
    def __setitem__(self, key, value):
        print 'Something is being set!'
        dict.__setitem__(self, key, value)
like image 38
Brian Goldman Avatar answered Sep 23 '22 14:09

Brian Goldman