Expert · Advanced Python · topic 43 of 50 · 30 min
Type hints
Explanation
What a type hint is
A type is the kind of a value: int, str, list and so on. A type hint (also called a type annotation) is a short label that says which type you expect. You write it after a colon for variables and parameters, and after an arrow -> for what a function returns.
city: str = "Chennai"
population: int = 7_000_000
def ticket_price(distance_km: float, is_senior: bool) -> float:
price = distance_km * 1.5
if is_senior:
price *= 0.6
return round(price, 2)
print(ticket_price(200, True))For containers, put the type of the items in square brackets. Since Python 3.9 you can use the normal built-in names for this.
| Hint | Means |
|---|---|
| list[int] | A list of whole numbers, like [90, 75, 62] |
| dict[str, float] | A dict with text keys and decimal values, like {"rice": 52.5} |
| tuple[str, int] | A tuple of exactly two items: a str then an int |
| tuple[int, ...] | A tuple of any length, all ints |
| set[str] | A set of strings |
Values that may be missing: Optional and X | None
Many functions return a value or None ("nothing found"). Write that as str | None (Python 3.10+). Older code writes the same thing as Optional[str], imported from the typing module. Both mean "a str, or None".
def find_phone(contacts: dict[str, str], name: str) -> str | None:
return contacts.get(name)
book = {"Anil": "98xxxxxx01"}
print(find_phone(book, "Anil"))
print(find_phone(book, "Zoya")) # NoneUnion means "one of these types". int | str (or Union[int, str] in older code) accepts either. A type alias is just a variable that holds a long hint, so you can give it a short, meaningful name and reuse it.
from typing import Union
PinCode = Union[int, str] # alias, old style
Cart = dict[str, tuple[int, float]] # item -> (quantity, price)
def cart_total(cart: Cart) -> float:
return sum(qty * price for qty, price in cart.values())
print(cart_total({"pen": (3, 10.0), "notebook": (2, 45.5)}))Hints are not checked when the program runs, and this surprises many learners. Python stores the hints but ignores them while running. Passing a str where an int is hinted gives no error from the hint itself. The code only fails later if the wrong type causes a real problem.
def double(n: int) -> int:
return n * 2
print(double("ha")) # haha (no error: hints are not enforced)A static type checker is a separate tool that reads your code without running it and reports type mistakes. The two common ones are mypy and pyright. Editors like VS Code (through the Pylance extension, which uses pyright) show these mistakes as red underlines as you type.
pip install mypy
mypy app.py
# app.py:4: error: Argument 1 to "double" has incompatible type "str"; expected "int"TypedDict describes a dict with fixed keys, each with its own type, which is handy for JSON data. Protocol describes "anything that has these methods", so a checker accepts any class that fits, without inheritance. Both come from the typing module; you will meet them in bigger projects.
from typing import TypedDict
class Student(TypedDict):
name: str
marks: int
def passed(s: Student) -> bool:
return s["marks"] >= 35
print(passed({"name": "Divya", "marks": 81}))
print(Student.__annotations__)
print(passed.__annotations__)Watch the lesson
Type hints · 1/6
This lesson is about type hints, the small labels that say what type each value should be.
Prefer a video by a teacher? Find free videos on “python type hints tutorial mypy” on YouTube ↗
In real life: Clear hints in an exam results service
A state board website calculates results for lakhs of students. Many developers work on the same code. With type hints, a new developer can see that grade() takes a list of marks and returns a grade string, and the team runs mypy in their checks so a mistake like passing a single number instead of a list is caught before the results go live.
def average(marks: list[int]) -> float:
return sum(marks) / len(marks)
def grade(marks: list[int]) -> str:
avg = average(marks)
if avg >= 75:
return "Distinction"
if avg >= 35:
return "Pass"
return "Fail"
print(grade([78, 82, 91]))
print(grade.__annotations__)Practice (0/3 done)
Write average(marks) with full type hints: marks is a list[float] and the function returns float | None. Return the average, or None for an empty list. (The checker reads average.__annotations__.)
Write hint_names(func) that reads func.__annotations__ and returns a dict from each name to the NAME of its type (use the type's __name__). For def f(name: str, age: int) -> bool, it returns {"name": "str", "age": "int", "return": "bool"}. Use simple types only (no list[...]).
Install mypy on your computer (pip install mypy). Write a small file with a hinted function, call it with a wrong type on purpose, and run mypy on the file. Then fix the call and run mypy again.
Quick quiz
Read more (free)
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.