7/13/2026

Understanding Python variable type hints (Dict, dict, and mypy)

When you read Python code, sooner or later you hit a line like this:

data: Dict[str, int] = {}

The : Dict[str, int] part looks strange the first time. In this post we'll figure out exactly what that one line means — and whether a "type hint" is actually enforced — using tiny runnable examples.

1. One line, three things at once

That single line is really three pieces glued together.

data  :  Dict[str, int]  =  {}
 │            │              │
name       type hint       actual
            (a note)        value
PieceMeaning
datathe variable name
: Dict[str, int]a type hint — "keys are str, values are int". Just a note for humans/editors
= {}the actual value = an empty dict

At runtime it is exactly the same as:

data = {}   # drop the hint and this is all that's left

2. = {} is just a dict

A dict is a "key → value" store. It has nothing to do with type hints — it's a basic built-in type that has always existed.

data = {}                 # empty dict
data["gemm"]   = "A"      # key (str) -> value
data["conv2d"] = "B"
print(data)               # {'gemm': 'A', 'conv2d': 'B'}
print(data["gemm"])       # A
print(list(data))         # ['gemm', 'conv2d']

3. : Dict[str, int] is a "type hint"

Dict[str, int] is a note saying "a dict whose keys are strings and values are integers". Python does not enforce that note when it runs.

from typing import Dict

ages: Dict[str, int] = {}   # at runtime this is just ages = {}
ages["alice"] = 30
ages["bob"]   = 25
print(ages)                 # {'alice': 30, 'bob': 25}

4. Is it really not enforced? — break it on purpose

Violating the hint does not raise an error. Let's prove it.

from typing import Dict

ages: Dict[str, int] = {}   # promise: "str keys, int values"
ages["alice"] = 30          # keeps the promise
ages["oops"]  = "not-int"   # value is a string -> breaks it
ages[123]     = 99          # key is an int      -> breaks it
print(ages)

Output:

{'alice': 30, 'oops': 'not-int', 123: 99}
Key point: a type hint is not enforced. The Python interpreter simply ignores it at runtime, so breaking it still runs fine.

5. So why write hints at all?

If they're not enforced, why bother? Because they're a "quality tool", not a rule.

  • Humans — reading the code, you instantly see "this is a str→int dict".
  • Editors (IDEs) — autocomplete, and a red squiggle when you misuse it.
  • Static checkers (mypy) — run mypy file.py separately and it catches violations before you run the code.
A hint is "a promise + documentation", not a check. To actually catch violations, run a tool like mypy yourself — the interpreter won't.

6. Dict vs dict — and when did this syntax appear?

The dict itself is old; the type-hint syntax is the newer part.

SyntaxImport needed?Introduced
Dict[str, int] (capital)from typing import DictPython 3.5 (2015)
dict[str, int] (lowercase)none (built-in)Python 3.9 (2020)
dict (plain)nonealways

Annotating a variable with x: int = 0 has been possible since Python 3.6 (2016). Both forms mean the same thing, so new code usually prefers the lowercase dict[...].

scores: dict[str, float] = {}   # 3.9+ : lowercase, no import

Summary

  • name: Type = value == name = value + (a type note)
  • = {} is just an empty dict (old, ordinary syntax)
  • : Dict[str, int] is a hint that is not enforced — breaking it still runs
  • hints are documentation for humans / editors / mypy; the checking is done by mypy, separately