I'm trying to write an abstract base class A which will have an abstract method run which the user/developer will be expected to overload. I would like to enforce some 'after' behaviour to be automatically applied to the derived class B, so that after B.run() has run it's course, another standard method will be called (in data pipelines this could e.g. commit or rollback transactions). Is there a way to achieve this?
My failed naive attempt at this is:
def do_the_other_thing(func):
def wrapper():
func()
print('doing the other thing!')
return wrapper
class A:
@do_the_other_thing
def run(self):
pass
class B(A):
def run(self):
print('running!')
B().run()
>>> 'running!'
>>> #'doing the other thing!' # <--- is there a way to get this?
I can of course implement a workaround by creating a different abstract method (e.g. _run) which is called from a non-abstract method A.run, but this is less elegant.
I can see that way back in 2007 PEP 3124 specified exactly this functionality but I can't find any modern reference to it.