Python
string conversion
class object
programming
tutorial

Convert string to Python class object?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Converting a string to a Python class object is really a lookup problem. The safe solution depends on where the class lives and how dynamic you want the system to be. In most cases, a registry or getattr on a known module is better than using eval.

Use an Explicit Registry When You Control the Classes

If the valid class names are known in advance, define a mapping from string to class:

python
1class CsvParser:
2    pass
3
4class JsonParser:
5    pass
6
7PARSERS = {
8    "csv": CsvParser,
9    "json": JsonParser,
10}
11
12name = "csv"
13parser_cls = PARSERS[name]
14print(parser_cls)

This is usually the best design because it is explicit, easy to validate, and safe for untrusted input.

Use getattr for Known Modules

If the class name comes from a module you control, import the module and look up the attribute:

python
1import importlib
2
3module = importlib.import_module("myapp.parsers")
4class_name = "CsvParser"
5parser_cls = getattr(module, class_name)
6print(parser_cls)

This is more dynamic than a registry, but it still stays inside a known namespace.

Avoid eval for This Job

You may see examples like:

python
parser_cls = eval(class_name)

This is usually the wrong approach. eval executes arbitrary expressions, which makes it unsafe for untrusted input and harder to reason about than a controlled lookup.

A registry or getattr expresses the intent more clearly and limits what names can be resolved.

Validate Before Instantiating

Once you have the class object, you may want to instantiate it:

python
instance = parser_cls()

But before doing that, it is often worth checking that the resolved object is actually the kind of class you expect. In plugin systems, for example, you may want to enforce inheritance from a base class or the presence of required methods.

Choose the Lookup Strategy by Trust Level

A practical rule is:

  • use a registry for trusted explicit choices
  • use getattr on a known module for dynamic plugin-style lookup
  • avoid eval unless you are solving a very unusual controlled case

The less open-ended the lookup needs to be, the easier it is to secure and maintain.

Dynamic Lookup Should Still Be Bounded

Even when the system is dynamic, define the namespace or registry that the lookup is allowed to search. Controlled flexibility is far easier to secure and debug than open-ended string execution.

Common Pitfalls

  • Using eval when a dictionary or getattr would be safer and clearer.
  • Looking in globals() and assuming the class is always present there.
  • Importing arbitrary module paths from untrusted input.
  • Instantiating the looked-up object before checking that it is the right class type.
  • Treating dynamic class lookup as magic instead of as a controlled namespace resolution problem.

Registries Also Improve Error Messages

When lookup goes through an explicit registry, you can return clearer errors such as which names are supported. That is another reason registries are often better than open-ended dynamic execution.

Dynamic Loading Still Needs a Trust Boundary

Even in plugin systems, decide which modules and class names are allowed before loading them. That one boundary decision does most of the work in keeping dynamic class lookup practical and safe.

Summary

  • Turning a string into a class object is usually a lookup operation, not a conversion trick.
  • A registry dictionary is the safest and clearest option when the valid classes are known.
  • 'getattr with importlib works well for controlled dynamic loading.'
  • 'eval is usually the wrong tool because it is too open and too risky.'
  • Validate the resolved class before instantiating it in plugin-style systems.

Course illustration
Course illustration

All Rights Reserved.