I want to create a class that wraps another class so that when a function is run through the wrapper class a pre and post function is run as well. I want the wrapper class t
You're almost there, you just need to do some introspection inside __getattr__
, returning a new wrapped function when the original attribute is callable:
class Wrapper(object):
def __init__(self,wrapped_class):
self.wrapped_class = wrapped_class()
def __getattr__(self,attr):
orig_attr = self.wrapped_class.__getattribute__(attr)
if callable(orig_attr):
def hooked(*args, **kwargs):
self.pre()
result = orig_attr(*args, **kwargs)
# prevent wrapped_class from becoming unwrapped
if result == self.wrapped_class:
return self
self.post()
return result
return hooked
else:
return orig_attr
def pre(self):
print ">> pre"
def post(self):
print "<< post"
Now with this code:
number = Wrapper(Simple)
print "\nCalling wrapped 'one':"
number.one()
print "\nCalling wrapped 'two':"
number.two("2")
The result is:
Calling wrapped 'one':
>> pre
one
<< post
Calling wrapped 'two':
>> pre
two2
<< post
I have just noticed in my original design there is no way of passing args and kwargs to the wrapped class, here is the answer updated to pass the inputs to the wrapped function...
class Wrapper(object):
def __init__(self,wrapped_class,*args,**kargs):
self.wrapped_class = wrapped_class(*args,**kargs)
def __getattr__(self,attr):
orig_attr = self.wrapped_class.__getattribute__(attr)
if callable(orig_attr):
def hooked(*args, **kwargs):
self.pre()
result = orig_attr(*args, **kwargs)
self.post()
return result
return hooked
else:
return orig_attr
def pre(self):
print ">> pre"
def post(self):
print "<< post"