Python 属性变更监听器模式

13 投票
2 回答
7034 浏览
提问于 2025-04-16 12:57

有没有人知道在Python中有没有简单的方法来跟踪字典对象的变化?我现在主要在做一些基本的增删改查操作,所以我有几个方法来处理字典的变化。如果字典发生了变化,我想调用一个函数,基本上就是做一个观察者/通知的功能。

 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()

我想避免的是那些跟踪变化的代码(设置布尔值)。我希望能有更简单的方法来跟踪变化。这只是一个简单的情况,但可能会有更复杂的逻辑,这样我就得设置变化标志了。

2 个回答

1

创建一个新的类,让它继承自 dict,然后重写 __setitem__ 这个方法。记得在你自己写的代码之后,调用一下 dict.__setitem__,这样才能确保你添加的内容真的被保存下来。

class Notifier(dict):
    def __setitem__(self, key, value):
        print 'Something is being set!'
        dict.__setitem__(self, key, value)
15

你可以从 dict 类派生出一个新类,并在字典发生任何变化时添加一个回调函数。这需要你重写任何会改变字典内容的方法:

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)

撰写回答