Йонатан, ваш вопрос не ясен! В зависимости от ситуации вы можете использовать много разных конструкций.
Одним из решений было бы иметь явные методы setup () и teardown (), которые вызываются методом run () перед вызовом runImpl (). Это позволит подклассам оборачивать / переопределять их по мере необходимости.
class Runner(object):
def run(self):
self.setup()
self.runImpl()
self.teardown()
def setup(self):
pass
def teardown(self):
pass
class RunnerImplementation(Runner):
def runImpl(self):
pass # do some stuff
def setup(self):
print "doing setup"
super(RunnerImplementation, self).setup()
def teardown(self):
print "doing teardown"
super(RunnerImplementation, self).teardown()
Однако, вы упомянули множественное наследование, что означает, что это не то направление, в котором вы должны идти.
Ваше упоминание множественного наследования и переноса (как в «декораторах») заставляет меня догадываться, что вы хотите иметь возможность писать разные реализации «бегунов», каждая со своим собственным процессом установки / разрыва, при повторном использовании частей установки / разрыв между "бегунами".
Если это так, вы можете определить ресурсы, которые знают, как настроить и демонтировать сами, и попросить каждого участника объявить, какие ресурсы ему требуются. Метод run () запускает соответствующий код установки / разрыва каждого ресурса и делает их доступными для метода runImpl ().
class Resource(object):
name = None # must give a name!
def setup(self):
pass
def teardown(self):
pass
class DatabaseResource(Resource):
name = "DB"
def setup(self):
self.db = createDatabaseConnection()
def teardown(self):
self.db.close()
class TracingResource(Resource):
name = "tracing"
def setup(self):
print "doing setup"
def teardown(self):
print "doing teardown"
class Runner(object):
RESOURCES = []
def run(self):
resources = {}
for resource_class in self.RESOURCES:
resource = resource_class()
resource.setup()
resources[resource_class.name] = resource
self.runImpl(resources)
# teardown in opposite order of setup
for resource in reversed(resources):
resource.teardown()
class RunnerA(Runner):
RESOURCES = [TracingResource, DatabaseResource]
def runImpl(self, resources):
resources['DB'].execute(...)