In python 3 I have a base class, from which a class is derived:
class Base:
# Tell the Base class to look and for pre/post
# functions the same name, and call them
def f(self):
print("f()")
def no_prepost(self): # should work, too
print("nothing")
class Derived(Base):
def pre_f(self):
print("pre_f()")
def post_f(self):
print("post_f()")
I want to call pre/post methods if they exists, but without explicitly stating them all the time:
foo = Derived()
# if exists: foo.pre_f() -- too verbose, do this automatically!
foo.f()
# if exists: foo.post_f()
A decorator function and some class introspection can do that. If a matching function is found it is called with the same arguments:
def prepost(f):
def prepost_wrapper(self, *args, **kwargs):
pre_name = 'pre_' + f.__name__
post_name = 'post_' + f.__name__
if hasattr(self, pre_name): getattr(self, pre_name) (*args, **kwargs)
ret = f(self, *args, **kwargs)
if hasattr(self, post_name): getattr(self, post_name)(*args, **kwargs)
return ret
return prepost_wrapper
class Base:
@prepost
def f(self, a, b=99):
print("f()", a, b)
@prepost
def missing(self):
print("nothing special here")
class Derived(Base):
def pre_f(self, a, b=0): # the arguments must match!
print("pre_f()", a, b)
def post_f(self, a, b=1):
print("post_f()", a, b)
foo = Derived()
foo.f("abc")
foo.missing()
foo.f("xyz", 12)
Output:
pre_f() abc 0
f() abc 99
post_f() abc 1
nothing special here
pre_f() xyz 12
f() xyz 12
post_f() xyz 12