Самое простое решение - это просто создать другой подкласс.
# assuming sensible bases:
class DB(object):
...
class Transformation(object):
def transform(self, obj):
...
def get(self, id):
return self.transform(super(Transformation, self).get(id))
class Cache(object):
def __init__(self, *args, **kwargs):
self.cache = Cache()
super(Cache, self).__init__(*args, **kwargs)
def get(self, id):
if id in self.cache:
return self.cache.get(id)
else:
self.cache.set(id, super(Cache, self).get(id))
return self.cache.get(id)
class DBwithTransformation(Transformation, DB):
# empty body
pass
Если вы упрямо отказываетесь назвать имя классу, вы можете позвонить type
напрямую. замена
class DBwithTransformation(Transformation, DB):
pass
db = DBwithTransformation(arg1, arg2, ...)
с
db = type("DB", (Transformation, DB), {})(arg1, arg2, ...)
Что не намного хуже, чем в примере с Scala.
Из-за тонкости системы типов Python, миксины, которые не наследуются от основного класса (DB
), появляются первыми в списке баз. В противном случае классы mixin не смогут корректно переопределить методы основного базового класса.
Эта та же тонкость может позволить вам иметь дополнительные функции в качестве правильных производных классов. Шаблон наследования алмазов не является проблемой; базовые классы появляются только один раз, независимо от того, сколько промежуточных базовых классов наследуют от них (в конце концов, все они в конечном счете наследуются от object
).