Dataclasses

MEDIUM2 min readby AdminJune 20, 2026History
0.0|0 ratingsLog in to rate

Introduced in Python 3.7, the `@dataclass` decorator automates the generation of boilerplates (such as `__init__()`, `__repr__()`, and comparisons) for classes ...

#ai-engineering#course#dataclasses

Definition

Introduced in Python 3.7, the @dataclass decorator automates the generation of boilerplates (such as __init__(), __repr__(), and comparisons) for classes primarily designed to hold structured data states.

Why It Exists

AI applications process rich structural responses (tokens, finish reasons, metadata, response models). Typing these as dicts leads to index key typos. Traditional class initializers require writing endless self.var = var lines. Dataclasses solve this, providing clean structured schemas with built-in validation capability.

How It Works

The decorator inspects class type annotations:

text
1
2
3
4
5
6
7
8
9
                  @dataclass DECORATOR
               ┌────────────────────────┐
               │ Class variables + Type │
               └───────────┬────────────┘
                           │
  Translates into standard Python bytecode including:
   - Dynamic __init__() with parameter assignments
   - Beautiful __repr__() string output formatting
   - Comparison support (__eq__, __lt__) out-of-the-box
  1. Auto-Assignment: Attributes are converted into parameter arguments inside an auto-generated initialization schema.
  2. Immutability (Optional): Setting frozen=True turns instances into immutable read-only records, which can also be hashed as dictionary keys.

Real-World Example

Example

In FastAPI / Pydantic APIs, dataclasses represent user profile inputs, structured response payloads, or model hyperparameter configuration blocks.

Python Example

Example

Here is a production dataclass representing an LLM response payload complete with post-initialization validation:

python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from dataclasses import dataclass, field
import time

@dataclass
class LLMResponse:
    """Structured data container representing model response metadata."""
    prompt: str
    response_text: str
    model_name: str
    input_tokens: int
    output_tokens: int
    execution_time: float = field(default=0.0)
    total_tokens: int = field(init=False) # Computed post-initialization

    def __post_init__(self):
        # Enforce validation checks
        if self.input_tokens < 0 or self.output_tokens < 0:
            raise ValueError("Token counts cannot be negative.")
        # Compute read-only/cached parameters
        self.total_tokens = self.input_tokens + self.output_tokens

# Demo
if __name__ == "__main__":
    resp = LLMResponse(
        prompt="Tell me a joke",
        response_text="Why do programmers wear glasses? Because they can't C#!",
        model_name="gemini-1.5-flash",
        input_tokens=4,
        output_tokens=12,
        execution_time=0.45
    )
    print(resp)
    print("Total Tokens:", resp.total_tokens)

Interview Questions

  • Beginner: Why use dataclasses instead of standard dictionaries?
  • Intermediate: What is the purpose of the __post_init__ method in a dataclass?
  • Advanced: How do you make a dataclass immutable (read-only) and hashable?

Interview Answers

  • Beginner: Dataclasses enforce static type hints, prevent runtime typos (since attributes are accessed via dot notation obj.name instead of string lookups obj["name"]), and auto-generate readable debugging strings (__repr__).
  • Intermediate: __post_init__ runs automatically after the compiler-generated __init__ is finished. It is used to perform parameter validation checks or calculate derived fields that depend on the initial inputs.
  • Advanced: Pass the parameter frozen=True to the decorator: @dataclass(frozen=True). This blocks modification of attributes after creation, automatically generating a __hash__ method that lets you use instances as dictionary keys or in sets.

Common Mistakes

  • Defining mutable defaults: Declaring tags: list = []. This raises a ValueError because mutable defaults are shared across instances. Use field(default_factory=list) instead.

Assignment

Write a dataclass called ChatMessage that takes role (str), content (str), and auto-assigns a timestamp float field using time.time inside __post_init__.


Discussion

Join the discussion! Sign in to leave comments and ask questions.

Loading discussion...