2014-04-05 3 views
2

내가 할 때 값 변경 감지 솔루션을 찾고 있습니다 : class_instance.list.append (value). 나는 나의 문제를 설명하기 위해 약간의 예를 썼다.목록을 사용하여 클래스 속성의 값 변경을 감지하고 추가하는 솔루션 찾기

class Foo(object): 

    def __setattr__(self, key, value): 
     print('set -> ', key, value) 
     self.__dict__[key] = value 

if __name__ == '__main__': 
    f = Foo() 
    #set/change detected 
    f.bar = ['foo'] 

    # change not detected 
    f.bar.append('bar') 

    #change detected 
    f.bar = ['foo', 'bar'] 

감사합니다.

+2

당신이 할 수있는 '티. 일반 목록을 사용하는 대신 "부모"에게 알리는 사용자 지정 데이터 형식을 사용해야합니다. – BrenBarn

+0

또는 자신의 메서드를 가질 수도 있고,'f.append_to ("bar", "foo")' – jonrsharpe

+0

@BrenBarn을 사용하면 __setitem__ 메서드를 재정의하고 List 유형 값을 TrackedList 클래스로 바꿀 수 있습니다. –

답변

1

@harobed의 도움으로이 솔루션 http://code.activestate.com/recipes/306864-list-and-dictionary-observer/을 발견했습니다. 관찰자 등급에 대한 Bernhard Mulder에게 크레딧이 적용됩니다. 여기

내가 이 게시물에 따라 유형을 감지하는 isinstance (A, 목록)에 의존하는 것이 좋습니다

class Foo(object): 

    def __init__(self): 
     self._dirty = False 

    def __setattr__(self, key, value): 
     if key != '_dirty': 
      if isinstance(value, list): 
       self.__dict__[key] = list_observer(value, self.observer(self)) 
      else: 
       self.__dict__[key] = value 
      self._make_dirty() 

    def _make_dirty(self): 
     self._dirty = True 
     print('is dirty') 

    def _not_dirty(self): 
     self._dirty = False 
     print('is no more dirty') 

    class observer(object): 
     """ 
     If a call to a method is made, this class prints the name of the method 
     and all arguments. 
     """ 

     def __init__(self, instance): 
      self.instance = instance 

     def p(self, *args): 
      print self.attr, args 
      self.instance._make_dirty() 

     def __getattr__(self, attr): 
      self.attr = attr 
      return self.p 


class list_observer(list): 
    """ 
    Send all changes to an observer. 
    """ 

    def __init__(self, value, observer): 
     list.__init__(self, value) 
     self.set_observer(observer) 

    def set_observer(self, observer): 
     """ 
     All changes to this list will trigger calls to observer methods. 
     """ 
     self.observer = observer 

    def __setitem__(self, key, value): 
     """ 
     Intercept the l[key]=value operations. 
     Also covers slice assignment. 
     """ 
     try: 
      oldvalue = self.__getitem__(key) 
     except KeyError: 
      list.__setitem__(self, key, value) 
      self.observer.list_create(self, key) 
     else: 
      list.__setitem__(self, key, value) 
      self.observer.list_set(self, key, oldvalue) 

    def __delitem__(self, key): 
     oldvalue = list.__getitem__(self, key) 
     list.__delitem__(self, key) 
     self.observer.list_del(self, key, oldvalue) 

    def __setslice__(self, i, j, sequence): 
     oldvalue = list.__getslice__(self, i, j) 
     self.observer.list_setslice(self, i, j, sequence, oldvalue) 
     list.__setslice__(self, i, j, sequence) 

    def __delslice__(self, i, j): 
     oldvalue = list.__getitem__(self, slice(i, j)) 
     list.__delslice__(self, i, j) 
     self.observer.list_delslice(self, i, oldvalue) 

    def append(self, value): 
     list.append(self, value) 
     self.observer.list_append(self) 

    def pop(self): 
     oldvalue = list.pop(self) 
     self.observer.list_pop(self, oldvalue) 

    def extend(self, newvalue): 
     list.extend(self, newvalue) 
     self.observer.list_extend(self, newvalue) 

    def insert(self, i, element): 
     list.insert(self, i, element) 
     self.observer.list_insert(self, i, element) 

    def remove(self, element): 
     index = list.index(self, element) 
     list.remove(self, element) 
     self.observer.list_remove(self, index, element) 

    def reverse(self): 
     list.reverse(self) 
     self.observer.list_reverse(self) 

    def sort(self, cmpfunc=None): 
     oldlist = self[:] 
     list.sort(self, cmpfunc) 
     self.observer.list_sort(self, oldlist) 


if __name__ == '__main__': 
    f = Foo() 

    #change detected, f is dirty 
    f.bar = ['foo'] 
    f._not_dirty() 

    #change detected, f is dirty again 
    f.bar.append('bar') 

편집을 달성하고자하는 어떤 작업 예제입니다 ->Differences between isinstance() and type() in python

관련 문제