self-aware list of objects able to sense constituent member alterations?
Reckoner
reckoner at gmail.com
Fri Jan 30 07:51:42 EST 2009
On Jan 28, 9:49 am, koranthala <koranth... at gmail.com> wrote:
> On Jan 28, 10:39 pm,Reckoner<recko... at gmail.com> wrote:
>
>
>
> > On Jan 28, 9:16 am, koranthala <koranth... at gmail.com> wrote:
>
> > > On Jan 28, 5:42 pm, koranthala <koranth... at gmail.com> wrote:
>
> > > > On Jan 28, 2:16 am,Reckoner<recko... at gmail.com> wrote:
>
> > > > > I'm not sure this is possible, but I would like to have
> > > > > a list of objects
>
> > > > > A=[a,b,c,d,...,z]
>
> > > > > where, in the midst of a lot of processing I might do something like,
>
> > > > > A[0].do_something_which_changes_the_properties()
>
> > > > > which alter the properties of the object 'a'.
>
> > > > > The trick is that I would like A to be mysteriously aware that
> > > > > something about the object 'a' has changed so that when I revisit A,
> > > > > I will know that the other items in the list need to be refreshed to
> > > > > reflect the changes in A as a result of changing 'a'.
>
> > > > > Even better would be to automatically percolate the subsequent changes
> > > > > that resulted from altering 'a' for the rest of the items in the list.
> > > > > Naturally, all of these items are related in some parent-child
> > > > > fashion.
>
> > > > > that might be a lot to ask, however.
>
> > > > > Any advice appreciated.
>
> > > > I think Python Cookbook has a recipe which deals with this.
> > > > - 6.12 Checking an Instance for Any State Change.
>
> > > Were you able to get this? If not, let me know. I will try to type it
> > > in here - (it is a big recipe, so not doing it now)
>
> > Actually, I have the python cookbook, but cannot find the recipe you
> > mention. maybe I have an older version?
>
> > thanks.
>
> Mine is 2nd Edition.
for posterity's sake, here's the recipe in question:
import copy
class ChangeCheckerMixin(object):
containerItems = {dict: dict.iteritems, list: enumerate}
immutable = False
def snapshot(self):
''' create a "snapshot" of self's state -- like a shallow
copy, but
recursing over container types (not over general
instances:
instances must keep track of their own changes if
needed). '''
if self.immutable:
return
self._snapshot = self._copy_container(self.__dict__)
def makeImmutable(self):
''' the instance state can't change any more, set .immutable
'''
self.immutable = True
try:
del self._snapshot
except AttributeError:
pass
def _copy_container(self, container):
''' semi-shallow copy, recursing on container types only '''
new_container = copy.copy(container)
for k, v in self.containerItems[type(new_container)]
(new_container):
if type(v) in self.containerItems:
new_container[k] = self._copy_container(v)
elif hasattr(v, 'snapshot'):
v.snapshot( )
return new_container
def isChanged(self):
''' True if self's state is changed since the last snapshot
'''
if self.immutable:
return False
# remove snapshot from self.__dict__, put it back at the end
snap = self.__dict__.pop('_snapshot', None)
if snap is None:
return True
try:
return self._checkContainer(self.__dict__, snap)
finally:
self._snapshot = snap
def _checkContainer(self, container, snapshot):
''' return True if the container and its snapshot differ '''
if len(container) != len(snapshot):
return True
for k, v in self.containerItems[type(container)](container):
try:
ov = snapshot[k]
except LookupError:
return True
if self._checkItem(v, ov):
return True
return False
def _checkItem(self, newitem, olditem):
''' compare newitem and olditem. If they are containers, call
self._checkContainer recursively. If they're an instance
with
an 'isChanged' method, delegate to that method.
Otherwise,
return True if the items differ. '''
if type(newitem) != type(olditem):
return True
if type(newitem) in self.containerItems:
return self._checkContainer(newitem, olditem)
if newitem is olditem:
method_isChanged = getattr(newitem, 'isChanged', None)
if method_isChanged is None:
return False
return method_isChanged( )
return newitem != olditem
if __name__ == '__main__':
class eg(ChangeCheckerMixin):
def __init__(self, *a, **k):
self.L = list(*a, **k)
def __str__(self):
return 'eg(%s)' % str(self.L)
def __getattr__(self, a):
return getattr(self.L, a)
x = eg('ciao')
print 'x =', x, 'is changed =', x.isChanged( )
# emits: x = eg(['c', 'i', 'a', 'o']) is changed = True
# now, assume x gets saved, then...:
x.snapshot( )
print 'x =', x, 'is changed =', x.isChanged( )
# emits: x = eg(['c', 'i', 'a', 'o']) is changed = False
# now we change x...:
x.append('x')
print 'x =', x, 'is changed =', x.isChanged( )
# emits: x = eg(['c', 'i', 'a', 'o', 'x']) is changed = True
More information about the Python-list
mailing list