Do Python type hints actually do anything at runtime?
Short answer
Type hints are not enforced when the code runs, so a wrong type does not raise on its own. They are for readers and for external checkers like mypy, which catch mismatches before you run the code.
The short version
Type hints are annotations that Python does not enforce at runtime. A function declared to take an int will happily run with a string and fail only if the body does something invalid. Their value is for people reading the code and for external tools like mypy or your editor, which check the types statically, before the program runs.
They do not enforce anything
def add(a: int, b: int) -> int:
return a + b
print(add("x", "y")) # "xy", no error at all
The hints say int, but passing strings works, because Python ignores the annotations when running. The + just happens to be valid for strings, so it concatenates. Nothing checks that the arguments matched the hints.
What they are actually for
Two things. First, documentation: a reader (including future you) sees immediately what a function expects and returns, which is clearer than guessing or reading the whole body. Second, static checking: a tool like mypy reads the hints and reports mismatches without running the code.
$ mypy script.py
script.py: error: Argument 1 to "add" has incompatible type "str"; expected "int"
This catches a whole class of bugs early, at the point you write them, rather than at run time on some unlucky input.
Common hint syntax
Modern Python (3.9 and later) lets you use the built-in containers directly, and | for optional or multiple types.
def totals(rows: list[dict[str, int]]) -> dict[str, int]:
...
def find(name: str) -> int | None: # returns an int or None
...
int | None is the current way to say "an int or nothing", replacing the older Optional[int] from the typing module.
The one place they can affect runtime
Some libraries do read annotations and act on them, which is the exception to "they do nothing". Dataclasses use them to generate fields, and frameworks like Pydantic and FastAPI use them to validate and parse data at runtime. So in those specific contexts the hints do have an effect, but that is the library reading them, not Python enforcing them.
Should you bother
For small scripts, hints are optional. For code others will use, or that you will maintain over time, they pay off: they document intent, let editors autocomplete and warn, and let a checker catch type errors before your users do. Add them to function signatures first, where they give the most benefit for the least effort.
Gradual adoption
You do not have to annotate everything at once. Type hints are designed to be added gradually, so you can annotate the tricky or public parts and leave the rest, and the checker will work with whatever you provide.