Skip to content Skip to sidebar Skip to footer

Python: Decorating A Class Method That Is Intended To Be Overwritten When Inherited

Let's say I have some base class: class Task: def run(self): #override this! Now, I want others to subclass Task and override the run() method: class MyTask(Task):

Solution 1:

As suggested in the comments, letting the subclasses override a hook instead of run itself would probably be best:

classTask(object):defrun(self):
        # before self.do_run()
        # afterclassMyTask(Task):defdo_run(self):
        ...

task = MyTask()
task.run()

However, this is one way you could do it with a class decorator:

defdecorate_run(cls):
    run = getattr(cls, 'run')
    defnew_run(self):
        print('before')
        run(self)
        print('after')
    setattr(cls, 'run', new_run)
    return cls


classTask(object): pass@decorate_runclassMyTask(Task):
    defrun(self):
        pass

task = MyTask()
task.run()

# prints:# before# after

Another way would be to use a metaclass. The advantage of using a metaclass would be that subclasses wouldn't have to be decorated. Task could be made an instance of the metaclass, and then all subclasses of Task would inherit the metaclass automatically.

classMetaTask(type):
    def__init__(cls, name, bases, clsdict):
        if'run'in clsdict:
            defnew_run(self):
                print('before')
                clsdict['run'](self)
                print('after')
            setattr(cls, 'run', new_run)

classTask(object, metaclass=MetaTask):
    # For Python2: remove metaclass=MetaTask above and uncomment below:# __metaclass__ = MetaTaskpassclassMyTask(Task):
    defrun(self):
        #successful override!pass

task = MyTask()
task.run()

Post a Comment for "Python: Decorating A Class Method That Is Intended To Be Overwritten When Inherited"