在我执行以下操作时,寻找检测值更改的解决方案: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']
感谢您的帮助。
答案 0 :(得分:3)
在@harobed的帮助下,我找到了这个解决方案http://code.activestate.com/recipes/306864-list-and-dictionary-observer/,并将观察员班级归功于Bernhard Mulder。
以下是我想要实现的工作样本
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')
EDIT 最好依靠isinstance(a,list)根据这篇文章检测类型 - > Differences between isinstance() and type() in python