Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Catching all methods before they execute

0 views
Skip to first unread message

jamesthie...@gmail.com

unread,
Mar 7, 2005, 1:15:27 PM3/7/05
to
I have run into some cases where I would like to run a class method
anytime any class method is invoked.
That is, if I write
x.foo

then it will be the same as writing
x.bar
x.foo

for any method in class x (with the possible exception of 'bar').

The first few times I wanted to print out a data structure for
debugging purposes. Most recently it was to save a data structure to
allow "undo" operations. I've realized that this is a generalized
problem and I was hoping that someone could point me to the correct
hook to accomplish this (python seems to have a hook for everything).

Michael Hoffman

unread,
Mar 7, 2005, 1:22:55 PM3/7/05
to
jamesthie...@gmail.com wrote:
> I have run into some cases where I would like to run a class method
> anytime any class method is invoked.

Perhaps you want __getattribute__ on a new-style class?
--
Michael Hoffman

jamesthie...@gmail.com

unread,
Mar 7, 2005, 2:08:02 PM3/7/05
to

Perhaps I do. The docs say that __getattribute__ is called on all
attribute references, so I tried to make an undoable list as follows:
% cat Undoable.py
class Undoable(object):
def __init__(self, superclass):
self.superclass = superclass
print "__init__"

def __getattribute__(self, name):
print "__getattribute__"
self.SaveState(self)
self.superclass.__getattribute__(self, name)

def SaveState(self):
print "SaveState"

def RestoreState(self):
pass

l = Undoable(list)
l = [1, 2, 3]
print l.count(1)
% python Undoable.py
__init__
1

It appears that __init__ in Undoable is called, count() in list is
called, but not __getattribute__ or SaveState in Undoable.

What don't I understand?

Michael Hoffman

unread,
Mar 7, 2005, 2:34:35 PM3/7/05
to
jamesthie...@gmail.com wrote:

> l = Undoable(list)
> l = [1, 2, 3]

You just rebound l, so it no longer refers to an Undoable, it
refers to a list. This design won't work, you need something
more like:

l = Undoable([1, 2, 3])

There were a few other pitfalls in your design... Here,
try something like this instead:

class SurrogateNotInitedError(exceptions.AttributeError):
pass

class Surrogate(object):
"""
the data is stored in _data

>>> list1 = [0, 1, 2, 3]
>>> list2 = [4, 5, 6, 7]
>>> surrogate = Surrogate(list1)
>>> surrogate.reverse()
>>> list1
[3, 2, 1, 0]
>>> surrogate._data = list2
>>> surrogate.append(8)
>>> list2
[4, 5, 6, 7, 8]
"""
def __init__(self, data):
self._data = data

def __getattr__(self, name):
if name == "_data":
raise SurrogateNotInitedError, name
else:
try:
return getattr(self._data, name)
except SurrogateNotInitedError:
raise SurrogateNotInitedError, name

You can modify this to make an UndoableSurrogate with appropriate saving
of state. Note the use of __getattr__ instead of __getattribute__. The
latter is not needed since there are not any attributes defined on
Surrogate instead.
--
Michael Hoffman

0 new messages