It is possible to create subclasses on the fly. This does not mean that you should. In any case, I will provide a mechanism.
The bases attribute in each class tells you the inheritance chain:
class Animal(object):
pass
class Dog(Animal):
pass
print Animal.__bases__
print Dog.__bases__
# prints:
#(<type 'object'>,)
#(<class '__main__.Animal'>,)
So, __bases__
is a tuple with the "inheritance bases". You can replace this tuple (you cannot "append to it" or "pop from it" because it is a a tuple, and tuples are immutable). For example, say that you have a "mixin class" which adds functionalities to some animal subclasses but not others:
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")
Produces the following output:
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
A lot of people consider MixIn classes evil. And they may be right! You can imagine that if you mess up the bases attribute, you pretty much destroyed your program. So, there it is - you can dynamically change the inheritance of an object, but it does not mean you should (probably abstract classes or concept implementation?)