Mateen Kiani
Published on Sat Aug 02 2025·4 min read
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.
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 = nameself.age = ageuser = User("Alice", 30)user_dict = user.__dict__print(user_dict) # {'name': 'Alice', 'age': 30}
This approach is quick, but note:
__dict__
(no @property
or slots).Tip: Clone the dict if you plan to modify it:
user_dict.copy()
.
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@dataclassclass Point:x: floaty: floatpt = Point(1.2, 3.4)pt_dict = asdict(pt)print(pt_dict) # {'x': 1.2, 'y': 3.4}
Benefits of dataclasses:
__init__
, __repr__
, __eq__
methods.asdict()
handles nested dataclasses.Tip: Use
field(default_factory=...)
for mutable defaults.
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 jsonclass Book:def __init__(self, title, authors):self.title = titleself.authors = authorsbook = Book("The Hobbit", ["Tolkien"])json_str = json.dumps(book.__dict__)book_dict = json.loads(json_str)print(book_dict) # {'title': 'The Hobbit', 'authors': ['Tolkien']}
See more on serialization in the JSON stringify guide.
For full control, implement your own to_dict()
:
class Order:def __init__(self, id, items, total):self.id = idself._items = items # protectedself.total = totaldef to_dict(self):return {"order_id": self.id,"items": [item.to_dict() for item in self._items],"total": self.total}
Advantages:
Tip: Keep
to_dict
logic simple to avoid hidden side effects.
When you need robust validation, nested schemas, or advanced features, libraries can help:
model.dict()
.Example with Pydantic:
from pydantic import BaseModelclass Product(BaseModel):name: strprice: floatp = Product(name="Pen", price=1.5)print(p.dict()) # {'name': 'Pen', 'price': 1.5}
Tip: Choose libraries based on project needs—avoid overkill for small scripts.
Nested objects require recursive conversion. Combine methods:
class Category:def __init__(self, name):self.name = nameclass Item:def __init__(self, title, category):self.title = titleself.category = categorydef 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'}}
For JSON round-trip parsing, see the JSON parser guide.
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 |
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.