DEV Community

Cover image for Converting Python Objects to Dict
Mateen Kiani
Mateen Kiani

Posted on • Originally published at milddev.com

Converting Python Objects to Dict

Introduction

Working with Python objects often means you need to turn them into dictionaries for serialization, debugging, or data transformation. Yet many developers overlook the simple mechanisms built into Python that can do this conversion cleanly and efficiently. How can you turn a custom class instance into a dict without endless boilerplate code?

You’ll discover several approaches—from the built-in __dict__ attribute to dataclasses.asdict, from the json module to third-party libraries like Pydantic. Understanding these methods helps you write cleaner code, improves maintainability, and prevents subtle bugs when serializing or inspecting your objects.

Using the dict Attribute

Every instance of a user-defined class stores its attributes in the special __dict__ attribute. You can access it directly:

class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

user = User("Alice", 30)
user_dict = user.__dict__
print(user_dict)  # {'name': 'Alice', 'age': 30}
Enter fullscreen mode Exit fullscreen mode

This approach is quick, but note:

  • It only includes attributes in __dict__ (no @property or slots).
  • It exposes private attributes and those you might not want to serialize.

Tip: Clone the dict if you plan to modify it: user_dict.copy().

Converting Dataclasses with asdict

Python’s dataclasses module (Python 3.7+) streamlines object definitions. It also provides asdict() to convert dataclass instances into recursively built dictionaries:

from dataclasses import dataclass, asdict

@dataclass
class Point:
    x: float
    y: float

pt = Point(1.2, 3.4)
pt_dict = asdict(pt)
print(pt_dict)  # {'x': 1.2, 'y': 3.4}
Enter fullscreen mode Exit fullscreen mode

Benefits of dataclasses:

  • Automatic __init__, __repr__, __eq__ methods.
  • asdict() handles nested dataclasses.
  • Cleaner and more type-safe definitions.

Tip: Use field(default_factory=...) for mutable defaults.

Leveraging the json Module

Sometimes you need a quick hack: serialize to JSON, then parse back to dict. It’s not the fastest, but it works for simple objects with JSON-friendly attributes:

import json

class Book:
    def __init__(self, title, authors):
        self.title = title
        self.authors = authors

book = Book("The Hobbit", ["Tolkien"])
json_str = json.dumps(book.__dict__)
book_dict = json.loads(json_str)
print(book_dict)  # {'title': 'The Hobbit', 'authors': ['Tolkien']}
Enter fullscreen mode Exit fullscreen mode

See more on serialization in the JSON stringify guide.

Writing a Custom to_dict Method

For full control, implement your own to_dict():

class Order:
    def __init__(self, id, items, total):
        self.id = id
        self._items = items  # protected
        self.total = total

    def to_dict(self):
        return {
            "order_id": self.id,
            "items": [item.to_dict() for item in self._items],
            "total": self.total
        }
Enter fullscreen mode Exit fullscreen mode

Advantages:

  • Exclude or rename fields.
  • Transform or validate values.
  • Handle nested objects precisely.

Tip: Keep to_dict logic simple to avoid hidden side effects.

Using Third-Party Libraries

When you need robust validation, nested schemas, or advanced features, libraries can help:

  • Pydantic: Data validation, parsing, and conversion. Use model.dict().
  • Marshmallow: Schema definitions, serialization, and deserialization.

Example with Pydantic:

from pydantic import BaseModel

class Product(BaseModel):
    name: str
    price: float

p = Product(name="Pen", price=1.5)
print(p.dict())  # {'name': 'Pen', 'price': 1.5}
Enter fullscreen mode Exit fullscreen mode

Tip: Choose libraries based on project needs—avoid overkill for small scripts.

Handling Nested and Complex Objects

Nested objects require recursive conversion. Combine methods:

class Category:
    def __init__(self, name):
        self.name = name

class Item:
    def __init__(self, title, category):
        self.title = title
        self.category = category

    def to_dict(self):
        return {
            "title": self.title,
            "category": self.category.__dict__
        }

cat = Category("Books")
item = Item("1984", cat)
print(item.to_dict())
# {'title': '1984', 'category': {'name': 'Books'}}
Enter fullscreen mode Exit fullscreen mode

For JSON round-trip parsing, see the JSON parser guide.

Performance Considerations

Benchmark before choosing a method:

Method Complexity Use Case
__dict__ O(n) Quick & simple
dataclasses.asdict O(n + nested) Typed structures
JSON round-trip O(n) + I/O Quick hack
Custom to_dict Custom Full control
  • For large datasets, avoid JSON round-trip.
  • Dataclasses are fast and lean for typed data.
  • Third-party libraries add overhead but give validation.

Conclusion

Converting Python objects to dictionaries is a common task that you can solve in multiple ways. The built-in __dict__ attribute offers a quick hack, while dataclasses.asdict provides a structured, recursive approach. The json module can act as a bridge for simple types, and custom to_dict methods give you full control. When your project demands validation and advanced serialization, look to Pydantic or Marshmallow.

By choosing the right method for your use case, you’ll write clearer, more maintainable code and avoid subtle bugs in serialization. Start with the simplest tool and scale up only when you need more features or safety.

Top comments (0)