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

T

TP

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)
 
A

Aaron \Castironpi\ Brady

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)

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.
 
G

Gabriel Genellina

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!
 
T

Terry Reedy

Gabriel said:
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
 
S

Steven D'Aprano

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/
 
M

Michele Simionato

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
 
G

Gabriel Genellina

En Tue, 07 Oct 2008 10:34:44 -0300, Michele Simionato
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).

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top