Dynamic subclass discovery in Python

I recently needed to re-work a custom parser in Python. The original implementation used a giant if-elif-else loop and was a pain to maintain. I managed to break the parser down into smaller chunks and ended up deleting a TON of code. I did this by setting up small classes to handle each different entity I wanted to parse, and pushed a lot of redundant functionality into the base class. However, I really didn't want to have a static list of available classes to maintain, so I decided to find a way to dynamically find all subclasses of a particular base.

Long story (... something something metaclasses something something ...) short, this is done using the __subclasses__() class method. Like it says on the box, this will return a list of all known subclasses of the given class. The only requirement is that the modules containing your subclasses must be imported.

Here's an overly-simplified example:


# pets.py

class ConfusedAnimal(object):
    @classmethod 
    def get_name (cls):
          return cls.__name__ 

def make_noise (self):
    raise NotImplemented ()

class Cat(ConfusedAnimal):
    def make_noise(self):
        return "Oink!"

class Dog(ConfusedAnimal):
    def make_noise(self):
        return "Hiss!"

def list_species():
    known_pets = ConfusedAnimal.__subclasses__()

    for pet in known_pets:
        print ("{}s go {}".format(pet.get_name(), pet().make_noise()))

Let's run it:


    > import pets
    > pets.list_species()
    Cats go Oink!
    Dogs go Hiss!

That's all there is to it! You could add a hundred new species and use dynamic imports, but list_species would never have to change.