コメントで示唆されているように、サブクラスがrun
それ自体ではなくフックをオーバーライドできるようにするのがおそらく最善です。
class Task(object):
def run(self):
# before
self.do_run()
# after
class MyTask(Task):
def do_run(self):
...
task = MyTask()
task.run()
ただし、これはクラス デコレータを使用して実行できる1 つの方法です。
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
別の方法は、メタクラスを使用することです。メタクラスを使用する利点は、サブクラスを装飾する必要がないことです。Task
メタクラスのインスタンスにすることができ、その後、すべてのサブクラスがTask
メタクラスを自動的に継承します。
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()