[ACCEPTED]-Is there a way to create subclasses on-the-fly?-subclassing

Accepted answer
Score: 36

I'm not sure if this is what you're looking 6 for, but you can use type to create subclasses 5 dynamically:

SubClass = type('SubClass', (EntityResource,), {})

Edit: To understand how type works, you 4 just need to translate how would you write 3 the class and translate that into a type call. For 2 example, if you want to write something 1 like:

class SubClass(EntityResource):
    A=1
    B=2

then, that would be translated to:

 SubClass = type('SubClass', (EntityResource,), {'A': 1, 'B': 2})

where:

  • The first argument is just the class name
  • The second argument is the list of parent classes
  • The third argument is the dictionary initialize the class object. This includes not only class attributes, but also methods.
Score: 5

It is possible to create subclasses on the 17 fly. This does not mean that you should. In 16 any case, I will provide a mechanism.

The 15 bases attribute in each class tells you the inheritance 14 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 13 bases". You can replace this tuple (you 12 cannot "append to it" or "pop from it" because 11 it is a a tuple, and tuples are immutable). For 10 example, say that you have a "mixin class" which 9 adds functionalities to some animal subclasses 8 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 7 lot of people consider MixIn classes evil. And 6 they may be right! You can imagine that 5 if you mess up the bases attribute, you pretty 4 much destroyed your program. So, there it 3 is - you can dynamically change the inheritance 2 of an object, but it does not mean you should 1 (probably abstract classes or concept implementation?)

Score: 1

When I hear "creating subclasses on the 15 fly" I understand "create objects that behave 14 differently on the fly", which is really 13 a question of configuration.

Is there anything you need 12 that you can't get by just reading in some 11 data and creating an object that decides 10 how it is going to behave based on what 9 it reads?

Here's the metaphor: I'm a handy 8 guy -- I can put together any IKEA item 7 you throw at me. But I'm not a different 6 person each time, I'm just the same handy 5 guy reading a different set of diagrams 4 and looking for different kinds of screws 3 and pieces of wood. That's my reasoning 2 for subclassing not being the natural solution 1 here.

More Related questions