监视对象更改的Python对象

时间:2009-10-15 19:16:52

标签: python hash

我想要一个Python对象,它将监视自上次签入以来其他对象是否已更改,可能是通过存储它们的哈希和比较。它的行为应该是这样的:

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

你知道这样的事吗?

5 个答案:

答案 0 :(得分:7)

以下是您的实施方案。请注意,您监视的对象必须是可清除和可选择的。另请注意使用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

答案 1 :(得分:2)

答案 2 :(得分:2)

我从Nick Craig-Wood那里偷走了这个想法,并把它改成了Mix-Class。对我来说,这更容易使用:

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

答案 3 :(得分:0)

我没有听说过这样的事情......但你可以很容易地写出来。使用字典存储名称:每个对象的哈希对,然后使用pickle模块保存字典。

答案 4 :(得分:0)

这是基于Oduvan的答案,但实现为装饰者而不是混合类:

from cPickle import dumps

#decorator for monitoring changes
def ChangesMonitor(cls):

    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)

    cls.is_changed = is_changed
    cls._cm_last_dump = None
    return cls

print 'Test Example'

#decorate your common class
@ChangesMonitor
class MyGreatObject(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

请注意,可以在@property行前添加def is_changed(self):,以使print my_obj.is_changed()成为print my_obj.is_changed。这可能被认为更加pythonic ......