Implementing An "after" Decorator On An Abstract Method
Solution 1:
You actually can not do what you want with a function decorator alone if you do not expect the user to decorate run
themselves. You can use class decorators, __init_subclass__
, or metaclasses
.
With a class decorator,
classA:
defrun(self):
passdefdo_the_other_thing(func):
defwrapper(*args, **kwargs):
func(*args, **kwargs)
print('doing the other thing!')
return wrapper
defpipeline_thing(cls):
cls.run = do_the_other_thing(cls.run)
# do some other workreturn cls
@pipeline_thingclassB(A):
defrun(self):
print("running!")
Or with __init_subclass__
classA:
defrun(self):
passdef__init_subclass__(cls):
super().__init_subclass__()
cls.run = do_the_other_thing(cls.run)
# do some other workclassB(A):
defrun(self):
print("running!")
Or with metaclasses
classAMeta(type):
def__init__(cls, name, bases, attrs, **kwargs):
super().__init__(name, bases, attrs)
cls.run = do_the_other_thing(cls.run)
# do some other workclassA(metaclass=AMeta):
defrun(self):
passclassB(A):
defrun(self):
print("running!")
This example is overkill for metaclasses (you are using metaclass.__init__
- the least powerful magic method in a metaclass and your behavior can be done with __init_subclass__
(this is the intended use of __init_subclass__
). Using a metaclass in this way will prevent your users from using metaclasses and it will unnecessarily complicate your code. If you need the pipeline to do more magic, you can use them (say if you need access to __new__
).
I would either use __init_subclass__
or a class decorator (@pipe
or something) that also presumably mixed B
with A
. As, alkasm mentioned, you can make A
inherit from abc.ABC
and decorate run
with abc.abstractmethod
to ensure subclasses implement it.
Solution 2:
Don't override run
; override a method that run
calls.
classA:
defrun(self):
self.do_run()
print('doing the other thing!')
defdo_run(self):
passclassB(A):
defdo_run(self):
print('running!')
Then
>>>B().run()
running!
doing the other thing!
Post a Comment for "Implementing An "after" Decorator On An Abstract Method"