advanced

Dataclasses & Typing

7 min readLast updated: 2026-07-12

Overview

Dataclasses generate boilerplate code for data-storage classes automatically. Type annotations support static analysis check lookups.

Learning Objectives

  • Define dataclasses using @dataclass.
  • Use type hints to document expected variable types.
  • Create immutable data classes using frozen=True.

Concept Explanation

Dataclasses (introduced in PEP 557) generate standard methods (like __init__, __repr__, and __eq__) automatically based on class variable type annotations. Frozen dataclasses (frozen=True) are read-only and hashable, making them suitable for dictionary keys.

Code Examples

Example 1 — Basics

This example introduces the fundamental syntax and concepts.

python
from dataclasses import dataclass
@dataclass
class Coord:
    x: int
    y: int

Example 2 — Everyday Usage

This example demonstrates a realistic scenario handling business parameters.

python
from dataclasses import dataclass

@dataclass(frozen=True) # Frozen instances are immutable
class ServerConfig:
    host: str
    port: int = 80

config = ServerConfig('127.0.0.1')
print(config)
# config.port = 8080 raises FrozenInstanceError

Example 3 — Advanced Example

This example shows clean, production-grade code structure following senior development standards.

python
from dataclasses import dataclass, field
from typing import List

@dataclass
class WorkBatch:
    batch_id: int
    # Use default_factory to create unique list lists for every instance
    logs: List[str] = field(default_factory=list)

b1 = WorkBatch(1)
b1.logs.append('Task start')
print(b1)

Visual Flow

The following execution flow represents the step-by-step evaluation inside the interpreter:

text
Class variable definitions → Parse decorator metadata → Generate dunder methods code → Instantiate instances

Common Mistakes

Review these common pitfalls when working with this topic:

  • Declaring mutable defaults directly (e.g. logs: list = []) instead of using default_factory, which raises a ValueError.
  • Expecting type annotations to enforce checks at runtime (type hints are not enforced by Python at runtime).
  • Declaring non-default fields after default fields, raising a TypeError.
  • Mutating attributes inside frozen=True dataclasses.

Best Practices

Enforce these Pythonic best practices in your codebase:

❌ Don't
python
class Point:
    def __init__(self, x: int, y: int):
        self.x = x
        self.y = y # Verbose constructor boilerplate
✅ Do
python
from dataclasses import dataclass
@dataclass
class Point:
    x: int
    y: int # Generated initializer automatically

Quick Revision

Use these key summaries for last-minute revision:

  • @dataclass decorator reduces boilerplate.
  • Automatically generates repr and eq.
  • Type hints are required for fields.
  • Use frozen=True for immutability.
  • Use default_factory for mutable defaults.
  • Type annotations are not enforced at runtime.