self-aware list of objects able to sense constituent member alterations?
Reckoner
reckoner at gmail.com
Wed Jan 28 14:06:21 EST 2009
On Jan 27, 9:46 pm, Steven D'Aprano
<ste... at REMOVE.THIS.cybersource.com.au> wrote:
> On Tue, 27 Jan 2009 13:16:36 -0800, Reckoner 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'.
>
> Can't be done if A is a built-in list, probably can't be done entirely
> generically, but you can probably do it in a cooperative manner.
>
> class TaintList(list):
> tainted = False
> def taint(self):
> self.tainted = True
> def untaint(self):
> self.tainted = False
>
> A = TaintList()
>
> import functools
> def taint(parent):
> def decorator(func):
> @functools.wraps(func)
> def f(*args, **kwargs):
> parent.taint()
> return func(*args, **kwargs)
> return f
> return decorator
>
> class TaintAwareThing(object):
> def __init__(self):
> self.attr = 0
> @taint(A)
> def change_attribute(self, x):
> self.attr = x
>
> >>> x = TaintAwareThing()
> >>> y = TaintAwareThing()
> >>> z = TaintAwareThing()
>
> >>> A.extend([x, y, z])
> >>> A.tainted
> False
> >>> x.change_attribute(5)
> >>> A.tainted
>
> True
>
> Here is a second approach: create a proxy class TaintThing that wraps
> whatever object you want, using delegation:
>
> class TaintThing(object):
> parent = A
> def __init__(self, obj):
> self.__dict__['_proxy'] = obj
> def __getattr__(self, attr):
> return getattr(self._proxy, attr)
> def __setattr__(self, attr, value):
> setattr(self._proxy, attr, value)
> self.parent.taint()
>
> Now change TaintList to automatically wrap anything stored in it:
>
> # untested
> class TaintList(list):
> def append(self, obj):
> list.append(self, TaintThing(obj))
> # similar for __setitem__, extend, insert
>
> --
> Steven
thanks for your reply.
For the second case where
> class TaintThing(object):
> parent = A
> def __init__(self, obj):
> self.__dict__['_proxy'] = obj
> def __getattr__(self, attr):
> return getattr(self._proxy, attr)
> def __setattr__(self, attr, value):
> setattr(self._proxy, attr, value)
> self.parent.taint()
you have told it that parent is 'A'. Shouldn't that be passed to it
somehow in the following:
> # untested
> class TaintList(list):
> def append(self, obj):
> list.append(self, TaintThing(obj))
> # similar for __setitem__, extend, insert
I apologize. I am probably missing something. This is getting pretty
advanced for me.
Thanks again.
More information about the Python-list
mailing list