我在Python中实现以下内容:(下面的代码框架)
class Base(object):
def __init__(self, run_ext):
def common_method1(self, run_ext):
def common_method2(self, run_ext):
def run_all(self):
"""Run all the methods beginning with run*"""
class Ext1(Base):
def run11(self):
def run12(self):
def notrelated11(self):
class Ext2(Base):
def run21(self):
def run22(self):
def notrelated21(self):
Ext1.run_all() # should run all the *'run*'* methods in Ext1 and
Ext2.run_all() # should run all the *'run*'* methods in Ext2.
目标: 在基类中实现run_all(),该类在调用时将从子类运行一组特定的方法。
思想: - 实现它的方法是通过显式调用子类中的方法并将父类中的run_all定义为抽象方法。 - 有点hacky方式是设置属性(或标识由其名称运行的方法)。
我正在寻找更好的替代解决方案..
注意:子类可能包含其他方法,而不仅仅是run1,run2 ..上面提到的not_related方法。
更新:正如@mkriheli指出的那样,基类不会/不应该知道从它继承的子类。
感谢。
答案 0 :(得分:2)
如何使用装饰器:
import inspect
def runnable(f):
setattr(f, '__can_run__', True)
return f
class Base:
def run_all(self):
for runner_name in inspect.getmembers(self, predicate=inspect.ismethod):
func = getattr(self, runner_name[0])
if hasattr(func, '__can_run__'):
if getattr(func, '__can_run__'):
func()
class Child(Base):
def __init__(self):
self.incremental = 0
@runnable
def run1(self):
self.incremental += 1
print "running", self.incremental
@runnable
def run2(self):
self.incremental += 1
print "running", self.incremental
c = Child()
c.run_all()
输出:
running 1
running 2
请注意,我不建议使用inspect
,并且您可能会以更好的方式尝试。 inspect
是一个CPython实现功能,并不保证在其他Python实现中存在。不要Wrong Thing To Do
。
答案 1 :(得分:0)
遵循@Nandeep的想法,免费检查
class runnable(object):
run_list = []
@staticmethod
def add(f):
runnable.run_list.append(f)
class Base:
def run_all(self):
for runner_name in runnable.run_list:
# Now you have all the functions
class Child(Base):
def __init__(self):
self.incremental = 0
@runnable.add
def run1(self):
self.incremental += 1
print "running", self.incremental