Focused practice · 9 min read

Python Type Hints Exercises: Annotations That Help Readers

Type hints are a communication tool. They tell a reader what a function expects and returns, and they give editors enough information to warn you before a bug reaches runtime. They do not turn Python into a statically checked language.

Annotate parameters and returns

A colon introduces a parameter annotation, and an arrow introduces the return annotation. Use built-in types for simple values. The annotations are stored in __annotations__ and are available to tools such as get_type_hints.

def greet(name: str) -> str:
    return f"Hello, {name}"
print(greet("Ada"))

A typed function

Describe collection contents

list[int] says the list contains integers; dict[str, float] says the keys are strings and the values are floats. These hints describe the interface, not each runtime value. A list containing a string can still be passed and will still run.

def total(values: list[int]) -> int:
    return sum(values)
print(total([1, 2, 3]))

Typed collections

Make missing values explicit

A lookup can return None. Write that possibility into the return type with a union such as float | None. The caller can then check for None before arithmetic, and an editor can point out the missing branch.

def find_price(prices: dict[str, float], item: str) -> float | None:
    return prices.get(item)
print(find_price({"tea": 3.5}, "coffee"))

A value that may be absent

Read hints at runtime when needed

get_type_hints resolves annotations into type objects. This is useful for small demos and frameworks. Most application code should not branch on annotations; use them to document and check, not to build a second type system.

from typing import get_type_hints
def double(n: int) -> int:
    return n * 2
print(get_type_hints(double))

Annotations are data too

Expect documentation, not enforcement

Passing a string where an int is annotated does not raise TypeError by itself. The function runs until an operation fails. Use a linter or a type checker in CI if you want static enforcement, and keep runtime validation for untrusted input.

def double(n: int) -> int:
    return n * 2
print(double("a"))

The hint does not convert the value

Your practice checklist

Common questions

Do type hints make Python faster?

Not by themselves. They are metadata used by tools; the interpreter does not enforce them.

Should I annotate every variable?

Usually no. Annotate function boundaries and values whose type is not obvious from the name and assignment.

What does list[int] mean on older Python?

On Python 3.8 and earlier, use List[int] from typing. Built-in generics are available in modern Python.

Practice type hints

12 questions on annotations, list[int], optional returns, and runtime behavior.

Open practice

Keep reading: