代码之家  ›  专栏  ›  技术社区  ›  Ram Rachum

监视对象更改的python对象

  •  4
  • Ram Rachum  · 技术社区  · 15 年前

    我想要一个python对象,它可以通过存储散列和比较来监视自上次签入以来其他对象是否发生了更改。它的行为应该是这样的:

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

    你知道这样的事吗?

    5 回复  |  直到 8 年前
        1
  •  7
  •   Nick Craig-Wood    15 年前

    下面是一个实现。请注意,您监视的对象必须是可哈希和可拾取的。同时注意使用 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
    
        3
  •  2
  •   NichtJens hnfl    8 年前

    我从尼克·克雷格·伍德那里偷了这个主意,把它改成了混合班。对我来说,这更容易使用:

    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
    
        4
  •  0
  •   steveha    15 年前

    我没听说过这样的事…但你可以很容易地写出来。使用字典存储每个对象的name:hash对,然后使用 pickle 用于保存字典的模块。

        5
  •  0
  •   NichtJens hnfl    8 年前

    这是基于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 . 这可能被认为是更多的蟒蛇…