wrapping a method function call?
Steven D'Aprano
steven at REMOVE.THIS.cybersource.com.au
Mon Nov 3 04:17:01 EST 2008
On Mon, 03 Nov 2008 08:17:02 +0000, mh wrote:
> I am instantiating a class A (which I am importing from somebody else,
> so I can't modify it) into my class X.
>
> Is there a way I can intercept or wrape calls to methods in A? I.e., in
> the code below can I call
>
> x.a.p1()
>
> and get the output
>
> X.pre
> A.p1
> X.post
Possibly you can do it with some metaclass magic. You might like to
search for Eiffel-style pre- and post-conditions using a metaclass,
although I warn you, many people consider metaclasses deep voodoo.
Here's one way using decorators:
# Define two decorator factories.
def precall(pre):
def decorator(f):
def newf(*args, **kwargs):
pre()
return f(*args, **kwargs)
return newf
return decorator
def postcall(post):
def decorator(f):
def newf(*args, **kwargs):
x = f(*args, **kwargs)
post()
return x
return newf
return decorator
Now you can monkey patch class A if you want. It's probably not a great
idea to do this in production code, as it will effect class A everywhere.
def pre(): print 'X.pre'
def post(): print 'X.post'
from module import A
A.p1 = precall(pre)(postcall(post)(A.p1))
Here's another way:
class A:
# in my real application, this is an imported class
# that I cannot modify
def p1(self): print 'A.p1'
class WrapA:
def __init__(self, ainstance, xinstance):
self._a = ainstance
self._x = xinstance
def p1(self):
# Delegate calls as needed.
self._x.pre()
self._a.p1()
self._x.post()
class X:
def __init__(self):
self.a = WrapA(A(), self)
def pre(self):
print 'X.pre'
def post(self):
print 'X.post'
There are probably many other ways to accomplish the same thing,
depending on your exact requirements. You should be able to combine the
decorator technique and the delegation technique to leave class A
untouched outside of class X, but wrapped inside of X.
--
Steven
More information about the Python-list
mailing list