2009-10-15 4 views
4

다른 오브젝트가 마지막으로 체크 인된 후 변경되었는지 여부를 모니터링하는 파이썬 오브젝트가 필요합니다. 아마도 해시를 저장하고 비교함으로써 모니터 할 것입니다. 그것은 다음과 같이 행동해야합니다 :오브젝트의 변화를 모니터하는 파이썬 오브젝트

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

당신은 그런 것을 알고 있습니까?

답변

6

을 포함 당신을위한 구현입니다. 모니터링하는 객체는 해시 가능이며 pickable이어야합니다. 또한 을 사용하면 모니터 된 개체가 삭제되지 않습니다. 즉, Monitor은 모니터링 대상 개체가 삭제되지 않도록합니다. 이

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

처럼 테스트를하는 경우

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 

은 내가 닉 크레이그 우드에서 아이디어를 훔쳐, 그리고 믹스 클래스로 변경

False 
True 
False 
+0

니스. 그 동안 나는 당신 자신과 비슷한 방식으로 그것을 직접 구현했습니다. 차이점은 해시를 사용한다는 것입니다. 왜 피클을 사용 했습니까? 더 낫니? –

+0

개체가 변경되면 해시가 변경되지는 않지만 피클은 분명히 변함을 알 수 있습니다. –

+0

알았어, 팁 주셔서 감사, 나는 피클을 사용하여 시작합니다. –

0

나는 이것에 관해 들어 본 적이 없다 ... 그러나 당신은 꽤 쉽게 쓸 수있다. 사전을 사용하여 각 객체에 대한 이름 : 해시 쌍을 저장 한 다음 pickle 모듈을 사용하여 사전을 저장하십시오.

2

인쇄합니다. 나를 위해,이 사용하기 쉽습니다 :

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 
0

이 Oduvan의 답변에 따라 않으며, 대신의 장식으로 구현 혼합 된 클래스 : @property가 추가 될 수

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 

하는 것으로 앞의 행은 print my_obj.is_changed()print my_obj.is_changed이됩니다. 이것은 더 평범한 것으로 간주 될 수 있습니다 ...

관련 문제