5 Best Ways to Instantiate Different Python Classes Dynamically

πŸ’‘ Problem Formulation: Python developers often encounter scenarios where they need to create object instances of various classes on-the-fly based on certain conditions or input data. For instance, given a class name as a string, or a selection from user input, the goal is to instantiate a class corresponding to that name without using static code references. This dynamic instantiation allows for more flexible and modular code.

Method 1: Using the globals() Function

This method leverages the globals() function to access the dictionary of the current module’s namespace, which contains all global variable names including classes. By using the class name as a key, we can instantiate a class dynamically.

Here’s an example:

class Dog:
    def speak(self):
        return "Woof!"

class Cat:
    def speak(self):
        return "Meow!"

class_name = 'Cat'
klass = globals()[class_name]()
print(klass.speak())

Output:

Meow!

The code snippet uses globals() to access the namespace, retrieves the class reference by name, and then instantiates an object using that reference which we then call its speak method on.

Method 2: Using the getattr() Function

The getattr() function can be applied to any module to retrieve an attribute by name. When applied to modules this can include classes which can then be instantiated dynamically.

Here’s an example:

import animals

class_name = 'Dog'
klass = getattr(animals, class_name)()
print(klass.speak())

Output:

Woof!

In this example, getattr() is used to fetch a class from the ‘animals’ module dynamically based on the class_name string. An instance of retrieved class is then created and we call the speak method.

Method 3: utilising the __import__() Function

The __import__() function is a low-level version of the import statement. It can be called with the name of a module to import, and from that module, we can then dynamically instantiate classes by name.

Here’s an example:

module_name = 'animals'
class_name = 'Dog'
module = __import__(module_name)
klass = getattr(module, class_name)()
print(klass.speak())

Output:

Woof!

This approach relies on dynamic importing of a module using the __import__() function, then fetching a class from it via getattr(), and finally, we create an instance from this class.

Method 4: Using a Custom Factory Function

A factory function can be designed to encapsulate the logic for dynamic instantiation, which can be reused throughout the application. It allows us to abstract away the instantiation process.

Here’s an example:

def factory(class_name):
    classes = {
        'Dog': Dog,
        'Cat': Cat
    }
    return classes[class_name]()

animal = factory('Dog')
print(animal.speak())

Output:

Woof!

The factory function defined uses a dictionary to map class names to class objects and then returns the instantiated object for the provided name. This centralizes dynamic instantiation logic.

Bonus One-Liner Method 5: Using the eval() Function

eval() can be used for dynamic instantiation, but it should be used with caution as it will execute any passed string as Python code which can be a security risk.

Here’s an example:

klass_instance = eval('Dog()')
print(klass_instance.speak())

Output:

Woof!

This snippet directly evaluates the string ‘Dog()’ as a Python expression, creating a new Dog instance, then calling its speak method immediately after creating it.

Summary/Discussion

  • Method 1: Using globals(). Straightforward. Limited to current global scope.
  • Method 2: Using getattr() on a module. Versatile. Requires module’s explicit import.
  • Method 3: Using __import__() function. Allows for dynamic import. More complex syntax.
  • Method 4: Custom factory function. Encapsulates logic. Requires updating when new classes are added.
  • Method 5: Using eval(). Extremely succinct. Significant security risks.