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

execute a function before and after any method of a parent class

6 views
Skip to first unread message

TP

unread,
Oct 3, 2008, 10:03:22 AM10/3/08
to
Hi everybody,

I would like to be able to specialize an existing class A, so as to obtain a
class B(A), with all methods of B being the methods of A preceded by a
special method of B called _before_any_method_of_A( self ), and followed by
a special method of B called _after_any_method_of_A( self ).

The goal is to avoid to redefine explicitly in B all methods of A.

Is this possible in Python?

Thanks a lot

Julien

--
python -c "print ''.join([chr(154 - ord(c)) for c in '*9(9&(18%.9&1+,\'Z
(55l4('])"

"When a distinguished but elderly scientist states that something is
possible, he is almost certainly right. When he states that something is
impossible, he is very probably wrong." (first law of AC Clarke)

Aaron "Castironpi" Brady

unread,
Oct 3, 2008, 1:45:11 PM10/3/08
to

Yes it's possible. The exact solution depends on how much control you
want, and over what. Do you want inheritance or delegation? Do you
want the same pre and post method for all inherited methods? Will you
always use single-inheritance? Would you mind using a list of names,
as a sort of midpoint between complete redefinition and completely
dynamic? Do you want class lookups to succeed? If so, what do you
want them to do?

Generally, you could build the class dynamically with a metaclass, or
use __getattr__ a lookup.

Gabriel Genellina

unread,
Oct 3, 2008, 3:23:28 PM10/3/08
to pytho...@python.org
En Fri, 03 Oct 2008 11:03:22 -0300, TP <Tribul...@paralleles.invalid>
escribiᅵ:

> I would like to be able to specialize an existing class A, so as to
> obtain a
> class B(A), with all methods of B being the methods of A preceded by a
> special method of B called _before_any_method_of_A( self ), and followed
> by
> a special method of B called _after_any_method_of_A( self ).
>
> The goal is to avoid to redefine explicitly in B all methods of A.
>
> Is this possible in Python?

Sure. After reading this (excelent!) article by M. Simionato
http://www.phyast.pitt.edu/~micheles/python/documentation.html you should
be able to write a decorator to make any method into a "sandwich"
(probably based on his "trace" example). Your code would look like this:

@decorator
def sandwich(f, self, *args, **kw):
self.before()
f(self, *args, **kw)
self.after()

class A:
@sandwich
def foo(self):
...

@sandwich
def bar(self, x):
...

Ok, but then you have to explicitely decorate every method. To avoid this,
you may use a metaclass; this article by Michael Foord explains how:
http://www.voidspace.org.uk/python/articles/metaclasses.shtml#a-method-decorating-metaclass

That's all!

--
Gabriel Genellina

Terry Reedy

unread,
Oct 3, 2008, 6:34:11 PM10/3/08
to pytho...@python.org
Gabriel Genellina wrote:
> En Fri, 03 Oct 2008 11:03:22 -0300, TP <Tribul...@paralleles.invalid>
> escribió:

>
>> I would like to be able to specialize an existing class A, so as to
>> obtain a
>> class B(A), with all methods of B being the methods of A preceded by a
>> special method of B called _before_any_method_of_A( self ), and
>> followed by
>> a special method of B called _after_any_method_of_A( self ).
>>
>> The goal is to avoid to redefine explicitly in B all methods of A.
>>
>> Is this possible in Python?
>
> Sure. After reading this (excelent!) article by M. Simionato
> http://www.phyast.pitt.edu/~micheles/python/documentation.html you
> should be able to write a decorator to make any method into a "sandwich"
> (probably based on his "trace" example). Your code would look like this:
>
> @decorator
> def sandwich(f, self, *args, **kw):
> self.before()
> f(self, *args, **kw)
> self.after()
>
> class A:
> @sandwich
> def foo(self):
> ...
>
> @sandwich
> def bar(self, x):
> ...
>
> Ok, but then you have to explicitely decorate every method. To avoid
> this, you may use a metaclass; this article by Michael Foord explains how:
> http://www.voidspace.org.uk/python/articles/metaclasses.shtml#a-method-decorating-metaclass

I believe this would work (untested, 3.0):

class A(): # define methods

class B(): pass
func = type(lambda:None)
for item in A.__dict__:
if isinstance(item, func):
setattr(B, item.__name__, sandwich(item))

tjr

Steven D'Aprano

unread,
Oct 3, 2008, 11:47:38 PM10/3/08
to
On Fri, 03 Oct 2008 16:03:22 +0200, TP wrote:

> Hi everybody,
>
> I would like to be able to specialize an existing class A, so as to
> obtain a class B(A), with all methods of B being the methods of A
> preceded by a special method of B called _before_any_method_of_A( self
> ), and followed by a special method of B called _after_any_method_of_A(
> self ).
>
> The goal is to avoid to redefine explicitly in B all methods of A.
>
> Is this possible in Python?

You may be able to adapt this code to do what you are after:


http://code.activestate.com/recipes/91192/

--
Steven

Michele Simionato

unread,
Oct 7, 2008, 9:34:44 AM10/7/08
to
On Oct 3, 9:23 pm, "Gabriel Genellina" <gagsl-...@yahoo.com.ar> wrote:

> Ok, but then you have to explicitely decorate every method. To avoid this,  

> you may use a metaclass; this article by Michael Foord explains how:http://www.voidspace.org.uk/python/articles/metaclasses.shtml#a-metho...

Since Python 2.6 is out, I would recommend using a class decorator for
this task.
The class decorator is not inherited, so in order to decorate methods
in subclasses
one has to repeat it, which I see as a feature (explicit is better
than implicit).
Otherwise the readers of your classes will not have any visual clue
that something
magic is going on; moreover, you will lower the risk of decorating
methods
that should not be decorated (I mean, in case of accidents).

Michele Simionato

Gabriel Genellina

unread,
Oct 7, 2008, 5:44:10 PM10/7/08
to pytho...@python.org
En Tue, 07 Oct 2008 10:34:44 -0300, Michele Simionato
<michele....@gmail.com> escribió:

Good to know, I was not aware of the difference.

--
Gabriel Genellina

0 new messages