Type hints don't change runtime behavior at all — Python remains dynamically typed, and nothing stops you from passing the "wrong" type at runtime. They exist purely for tooling: static type checkers (mypy, pyright), IDE autocomplete, and documentation.
def greet(name: str, times: int = 1) -> str:
return (name + " ") * times
from typing import Optional, Union
def find_user(user_id: int) -> Optional[dict]: # returns a dict, or None
...
def parse(value: Union[str, int]) -> int: # accepts either type
return int(value)
# Python 3.10+ shorthand for Union
def parse(value: str | int) -> int:
return int(value)
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
p = Point(3.0, 4.0) # __init__, __repr__, and __eq__ are generated automatically
@dataclass generates __init__, __repr__, and __eq__ from the type-annotated class body, eliminating a large amount of the boilerplate that a hand-written data-holding class otherwise needs — a genuinely common pattern in modern Python for classes whose main job is holding a handful of related fields.