我想要一个Python对象,它将监视自上次签入以来其他对象是否已更改,可能是通过存储它们的哈希和比较。它的行为应该是这样的:
>>> library = Library()
>>> library.is_changed(object1)
False
>>> object1.change_somehow()
>>> library.is_changed(object1)
True
>>> library.is_changed(object1)
False
你知道这样的事吗?
答案 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)
听起来你正在描述observer pattern。点击这里:
答案 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 ......