监控对象变化的Python对象

5 投票
5 回答
5203 浏览
提问于 2025-04-15 15:06

我想要一个Python对象,它可以监控其他对象自上次检查以来是否发生了变化,可能是通过存储它们的哈希值并进行比较来实现的。它的工作方式大概是这样的:

>>> library = Library()
>>> library.is_changed(object1)
False
>>> object1.change_somehow()
>>> library.is_changed(object1)
True
>>> library.is_changed(object1)
False

你知道有没有类似的东西吗?

5 个回答

2

听起来你在说的是一种叫做观察者模式的东西。你可以看看这里:

2

我从Nick Craig-Wood那里借用了这个想法,然后把它改成了一个混合类。对我来说,这样用起来更简单:

from cPickle import dumps

#base class for monitoring changes
class ChangesMonitor:
    _cm_last_dump = None
    def is_changed(self):
        prev_dump = self._cm_last_dump
        self._cm_last_dump = None
        cur_dump = dumps(self, -1)
        self._cm_last_dump = cur_dump
        return (prev_dump is not None) and (prev_dump != cur_dump)

if __name__ == '__main__':
    print 'Test Example'

    #mix monitoring class with your regular class
    class MyGreatObject(ChangesMonitor, object):
        one_val = 5
        second_val = 7
        def some_changes(self):
            self.second_val += 5

    #and testing
    my_obj = MyGreatObject()
    print my_obj.is_changed() #False
    print my_obj.is_changed() #False
    my_obj.some_changes()
    print my_obj.is_changed() #True
    print my_obj.is_changed() #False
9

这里有一个实现的例子。请注意,你监控的对象必须是可哈希和可序列化的。同时要注意使用了一个叫做 WeakKeyDictionary 的东西,这意味着 Monitor 不会阻止被监控的对象被删除。

from weakref import WeakKeyDictionary
from cPickle import dumps

class Monitor():
    def __init__(self):
        self.objects = WeakKeyDictionary()
    def is_changed(self, obj):
        current_pickle = dumps(obj, -1)
        changed = False
        if obj in self.objects:
            changed = current_pickle != self.objects[obj]
        self.objects[obj] = current_pickle
        return changed

class MyObject():
    def __init__(self):
        self.i = 1
    def change_somehow(self):
        self.i += 1

如果你这样测试它

object1 = MyObject()
monitor = Monitor()
print monitor.is_changed(object1)
object1.change_somehow()
print monitor.is_changed(object1)
print monitor.is_changed(object1)

它会打印出

False
True
False

撰写回答