You could use a metaclass, which wraps method1
at the time the class is created:
from functools import wraps
class MetaA(type):
def __new__(meta, name, bases, attr):
method1 = attr['method1']
if not getattr(method, '__isabstractmethod__'):
@wraps(method1)
def wrapper(self, *args, **kw):
res = method1(self, *args, **kw)
self.method2()
return res
attr['method1'] = wrapper
return super(MetaA, meta).__new__(meta, name, bases, attr)
class A(object):
__metaclass__ = MetaA
@abc.abstractmethod
def method1(self):
raise Exception("Unimplemented method")
def method2(self):
print "method1 finished"
This applies what is basically a decorator to a specific method whenever a (sub)class is created.
Another approach, somewhat hackish, is to intercept the method access, but would work. You'd implement a __getattribute__
hook on A
that adds a wrapper:
from functools import wraps
class A(object):
@abc.abstractmethod
def method1(self):
raise Exception("Unimplemented method")
def method2(self):
print "method1 finished"
def __getattribute__(self, name):
obj = super(A, self).__getattribute__(name)
if name == 'method1':
@wraps(obj)
def wrapper(*args, **kw):
res = obj()
self.method2()
return res
return wrapper
return obj
Either approach results in:
>>> B().method1()
executing method1 from class B
method1 finished
By using the @functools.wraps()
decorator the wrapper maintains several important attributes from the wrapped method, like its name and docstring.