Jus*_*tin 7 python inheritance decorator
假设我有一些基类:
class Task:
def run(self):
#override this!
Run Code Online (Sandbox Code Playgroud)
现在,我希望其他人继承Task并覆盖run()方法:
class MyTask(Task):
def run(self):
#successful override!
Run Code Online (Sandbox Code Playgroud)
但是,问题是必须在每个继承Task的类的run()方法之前和之后发生逻辑.
似乎我可以这样做的一种方法是在基类中定义另一个方法,然后调用run()方法.但是,我想问一下,有没有办法用装饰器来实现这个目的?这样做的最pythonic方式是什么?
unu*_*tbu 10
正如评论中所建议的那样,让子类覆盖一个钩子而不是run
它自己可能是最好的:
class Task(object):
def run(self):
# before
self.do_run()
# after
class MyTask(Task):
def do_run(self):
...
task = MyTask()
task.run()
Run Code Online (Sandbox Code Playgroud)
然而,这是一种方式,你可以用一个类装饰做到这一点:
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
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用元类.使用元类的优点是不必对子类进行修饰.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()
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3578 次 |
最近记录: |