programmation - python class object



Python: Décorer une méthode de classe qui est destinée à être écrasée lorsqu'elle est héritée (1)

Comme suggéré dans les commentaires, laisser les sous-classes remplacer un hook au lieu de run serait probablement le meilleur:

class Task(object):
    def run(self):
        # before 
        self.do_run()
        # after

class MyTask(Task):
    def do_run(self):
        ...

task = MyTask()
task.run()

Cependant, c'est une façon de le faire avec un décorateur de classe:

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


class Task(object): pass

@decorate_run
class MyTask(Task):
    def run(self):
        pass

task = MyTask()
task.run()

# prints:
# before
# after

Une autre façon serait d'utiliser une métaclasse. L'avantage d'utiliser une métaclasse serait que les sous-classes ne devraient pas être décorées. Task pourrait être une instance de la métaclasse, puis toutes les sous-classes de Task hériteraient automatiquement de la métaclasse.

class MetaTask(type):
    def __init__(cls, name, bases, clsdict):
        if 'run' in clsdict:
            def new_run(self):
                print('before')
                clsdict['run'](self)
                print('after')
            setattr(cls, 'run', new_run)

class Task(object, metaclass=MetaTask):
    # For Python2: remove metaclass=MetaTask above and uncomment below:
    # __metaclass__ = MetaTask
    pass

class MyTask(Task):
    def run(self):
        #successful override!
        pass

task = MyTask()
task.run()

Disons que j'ai une classe de base:

class Task:
    def run(self):
        #override this!

Maintenant, je veux que les autres sous-classent la tâche et remplacent la méthode run ():

class MyTask(Task):
    def run(self):
        #successful override!

Cependant, le problème est qu'il y a une logique qui doit avoir lieu avant et après la méthode run () de chaque classe qui sous-classe Task.

Il me semble qu'une façon de le faire serait de définir une autre méthode dans la classe de base qui appelle ensuite la méthode run (). Cependant, je voulais demander, y at-il un moyen d'y parvenir avec les décorateurs? Quelle serait la façon la plus pythonique de le faire?





decorator