Python Dynamic Dispatch from a String

dispatchpython

Lets assume I have a string for a class name (or part of a class name), and I have implementation somewhere. All I want, is to be able to get an instance of a class with the name in the variable.

For example,

dynamic_class_name = "Circle"  # not a constant, comes from somewhere
corresponding_class = some_magic(dynamic_class_name)
corresponding_instance = corresponding_class()

I can think of several approaches from using __import__() function, module attribute lookups, adding register to classes, other ways of using namespaces, making auto-registering via metaclassing, all the way to using some heavy component architecture and interfaces…

The question is, what would be the simplest but elegant (understandable, intuitive, regular, not hackish) way to replace ugly code like?

if dynamic_class_name == "Circle":
  inst = Circle()
elif dynamic_class_name == "Square":
  inst = Square()
...

The bonus would be to have minimal impact on IDE's (like PyCharm) ability to infer types and instances.

Also a plus is that there is no need to have a special list with the classes in one place, so new classes can be drop in.

Best Answer

One idea off the top of my head would be to create a dictionary holding your classes. This would mean that you can have the instantiation and error handling on very few lines.

>>> class Circle():
...     pass
... 
>>> class Square():
...     pass
... 
>>> d = { "square": Square, "circle": Circle}
>>> d["square"]()
<__main__.Square instance at 0x7ffbb1408e60>

I can't really say that it's very clear what's happening, but good naming and a few helpful comments would likely alleviate that; such as calling your dictionary instantiators or something similar. You will also need to collect the classes in some manner.

Here are some other suggestions:

You could potentially use one of the methods mentioned in those answers and wrap it up in a function with a descriptive name.

Having written some dynamic code of similar style in other languages I find that you typically, unsurprisingly, end up with code that is harder to read and much more complex in general. For all its inelegance the if else solution you have is understandable for everyone who knows even a little bit of basic programming.