Writing hints
A type hint is a note in the code that says what kind of value belongs where. On line 2, n: int says n should be an int (a whole number), and -> int says double gives back an int.
Run the file and Python reaches the def line. It builds the function and files its hints in a dictionary, double.__annotations__: n maps to int, return maps to int. Python stores the hints; it does not check them.
Run time
Line 4 calls double(21). Python gives n the value 21 and runs line 3, return n * 2. The value fits the hint, but Python never looked: it does not read hints while the program runs.
21 * 2 is 42, an int, just as the hint promised. print() writes 42 in the terminal and Python moves on to line 5.
Line 5 passes the string "ha" where the hint asks for an int. Python does not compare the value with the hint, so nothing stops the call: n is now "ha" and line 3 runs as usual.
"ha" * 2 repeats the text, so double returns "haha", a string, not the int its hint promised. The program still ends without an error. Python does not enforce type hints when it runs.
Check time
A type checker is a separate tool that reads your code without running it. Here it is mypy: run mypy hints.py and it compares every value it can work out with the hints.
mypy sees that line 5 passes a str where n: int asks for an int. It names the line and the problem without running anything, so you find the bug before your users do.
Change line 5 to double(int("21")): int() turns the text "21" into the number 21. mypy checks the file again and finds no issues, and the program now prints 42 twice.
Try it yourself
;; step 1/9 · line 2: def double(n: int) -> int:
def double(n: int) -> int: # n should be an int; returns an int
return n * 2
# variables can carry a hint too:
count: int = 0
names: list[str] = []
maybe: int | None = None # an int, or None
The typing documentation says it plainly: the Python runtime does not enforce function and variable type annotations. Tools such as type checkers, IDEs and linters use them. mypy prints each message on one long line; the terminal in the figure wraps it, and an indented row continues the row above.