03open 25 min

Data and state modeling: dicts, classes, dataclasses, and when to add type hints

Model Python data clearly without trying to recreate Rust's enum- and type-driven precision everywhere.

by the end of this lesson you can

  • Chooses an appropriate Python data shape
  • Adds type hints where they improve clarity
  • Avoids using hints just to mimic Rust's type density

Overview

Rust developers often rely on structs, enums, and rich type distinctions to make data shape and legal states explicit. Python can still be clear, but its normal toolbox looks different: dicts for flexible shapes, dataclasses for named fields, classes for behavior, and type hints when they improve readability or tooling.

In Rust, you often

encode domain shape precisely with structs, enums, and types that narrow what values are legal.

In Python, the common pattern is

to choose among dicts, dataclasses, classes, and optional type hints based on how much explicitness the code actually needs.

why this difference matters

This lesson helps Rust developers stop seeing Python modeling as under-specified and start seeing it as a set of lighter-weight tools with different tradeoffs.

Rust

struct User {
    name: String,
    admin: bool,
}

Python

from dataclasses import dataclass

@dataclass
class User:
    name: str
    is_admin: bool = False

Deeper comparison

Rust version

enum Job {
    Queued,
    Failed(String),
    Done,
}

Python version

job = {
    "status": "failed",
    "message": "timeout",
}

Reflect

When does Python need more explicit shape through dataclasses and type hints, and when is a simpler structure enough?

what a strong answer notices

A strong answer mentions reuse, boundary clarity, editor and type-checker benefits, and the fact that not every internal shape needs Rust-level modeling precision.

Rewrite

Rewrite this Rust data model into Python and choose where type hints actually help.

Rewrite this Rust

struct Config {
    region: String,
    retries: u32,
}

what good looks like

  • Chooses an appropriate Python data shape
  • Adds type hints where they improve clarity
  • Avoids using hints just to mimic Rust's type density

Practice

Design a Python model for ingested records that starts lightweight but becomes more explicit at the point where validation and repeated access matter.

success criteria

  • Uses Python data-shape options intentionally
  • Explains when to add type hints or dataclasses
  • Keeps the design readable without over-modeling

Common mistakes

  • Treating every dict as bad design because Rust would have used a struct or enum.
  • Adding type hints everywhere without improving clarity.
  • Trying to rebuild exhaustive enum-style modeling in places where Python wants lighter structure.

takeaways

  • This lesson helps Rust developers stop seeing Python modeling as under-specified and start seeing it as a set of lighter-weight tools with different tradeoffs.
  • A strong answer mentions reuse, boundary clarity, editor and type-checker benefits, and the fact that not every internal shape needs Rust-level modeling precision.
  • Uses Python data-shape options intentionally