метод декоратора python3, унаследованный от дочернего класса

#python #python-3.x #python-decorators

#python #python-3.x #python-декораторы

Вопрос:

 def after_finish(func):

    def _decorator(*args, **kwargs):
        ret = func(*args, **kwargs)
        print('after finish!')
        return ret

    return _decorator

class AbstractTask:
    @after_finish
    def run(self):
        raise NotImplementedError

class ConcreteTask1(AbstractTask):
    def run(self):
        # do concrete task here
        return 0

  

поскольку в приведенном выше коде у меня есть абстрактный AbstractTask тип и несколько дочерних классов, я хотел бы поместить after_finish декоратор в run метод, который является общим поведением, применимым ко всем подклассам. Как я могу достичь этой цели, поместив декоратор только один раз? Или есть какие-либо другие подходы, которые делают то же самое в синтаксисе python3?

Ответ №1:

Вы можете использовать второй метод, чтобы

  • общедоступный, который вы вызываете : run
  • частный, который вы переопределяете : _run

использование abstractmethod может помочь вашей IDE предупредить вас, если вы забыли реализовать метод

 from abc import abstractmethod

def after_finish(func):
    def _decorator(*args, **kwargs):
        ret = func(*args, **kwargs)
        print('after finish!')
        return ret
    return _decorator

class AbstractTask:
    @after_finish
    def run(self):
        self._run()

    @abstractmethod
    def _run(self):
        raise NotImplementedError

class ConcreteTask1(AbstractTask):
    def _run(self):
        return 0

if __name__ == '__main__':
    c = ConcreteTask1()
    c.run()