Можно создавать подклассы на лету. Это не значит, что ты должен. В любом случае я предоставлю механизм.
Атрибут base в каждом классе указывает цепочку наследования:
class Animal(object):
pass
class Dog(Animal):
pass
print Animal.__bases__
print Dog.__bases__
# prints:
#(<type 'object'>,)
#(<class '__main__.Animal'>,)
Итак, __bases__
- это кортеж с «основами наследования». Вы можете заменить этот кортеж (вы не можете «добавлять к нему» или «извлекать из него», потому что это кортеж, а кортежи неизменны). Например, скажем, что у вас есть «класс mixin», который добавляет функциональность некоторым подклассам животных, но не другим:
class Animal(object):
pass
class Dog(Animal):
pass
class Cat(Animal):
pass
class TalkMixin(object):
def talk(self):
print("I talk like a {0}".format(self.__class__.__name__))
if __name__ == "__main__":
dog = Dog()
cat = Cat()
try:
dog.talk()
cat.talk()
except AttributeError:
print("Great - the program raised AttributeError, as expected")
# now, add the MixIn to the class "Dog", but not to the class
# "Cat" - do this on the fly:
old_dog_bases = Dog.__bases__
Dog.__bases__ = (Animal, TalkMixin)
# this should be successful!
dog.talk()
try:
cat.talk()
except AttributeError:
print("As expected, cat.talk() raised AttributeError")
# now do the same (add the mixin dynamically - via inheritance) to
# the Cat
old_cat_bases = Cat.__bases__
Cat.__bases__ = (Animal, TalkMixin)
# this should be successful!
cat.talk()
# Now, remove the mixin (drop from the inheritance) for both cats
# and dogs:
Dog.__bases__ = old_dog_bases
Cat.__bases__ = old_cat_bases
try:
dog.talk()
cat.talk()
except AttributeError:
print("as expected, they can no longer talk")
Создает следующий вывод:
Great - the program raised AttributeError, as expected
I talk like a Dog
As expected, cat.talk() raised AttributeError
I talk like a Cat
as expected, they can no longer talk
Многие люди считают классы MixIn злыми. И они могут быть правы! Вы можете себе представить, что если вы испортили атрибут base , вы в значительной степени разрушили вашу программу. Итак, это так - вы можете динамически изменять наследование объекта, но это не значит, что вы должны (вероятно, абстрактные классы или реализация концепции?)