Type hinting in Python is a way to indicate the expected data types of variables, function arguments, and return values. It improves code readability, debugging, and static analysis without affecting runtime performance.
1. Why Use Type Hinting?
Improves code readability and maintainability
Catches type-related errors early (before runtime)
Helps IDEs provide better auto-completion and linting
Assists in team collaboration with clearer function signatures
2. Basic Type Hints
Python introduced type hints in PEP 484 (Python 3.5). The basic syntax uses colons (:
) and arrows (->
).
a) Function Annotations
def add(x: int, y: int) -> int:
return x + y
result = add(5, 10)
print(result) # Output: 15
x: int
→ Argumentx
is expected to be anint
.y: int
→ Argumenty
is expected to be anint
.-> int
→ The function returns anint
.
b) Variable Annotations
name: str = "Alice"
age: int = 25
height: float = 5.9
is_student: bool = False
Type hints do not enforce types at runtime but help tools like MyPy detect issues.
3. Advanced Type Hinting
a) Using List
, Tuple
, and Dict
(from typing
module)
from typing import List, Tuple, Dict
names: List[str] = ["Alice", "Bob", "Charlie"]
coordinates: Tuple[float, float] = (12.34, 56.78)
student_scores: Dict[str, int] = {"Alice": 90, "Bob": 85}
b) Using Union
(Multiple Types Allowed)
from typing import Union
def process_value(value: Union[int, float]) -> float:
return value * 2.5
print(process_value(10)) # Output: 25.0
print(process_value(3.5)) # Output: 8.75
Union[int, float]
→ The argument can be either anint
orfloat
.
c) Using Optional
(None Allowed)
from typing import Optional
def get_name(name: Optional[str] = None) -> str:
return name if name else "Unknown"
print(get_name("Alice")) # Output: Alice
print(get_name()) # Output: Unknown
Optional[str]
→ The argument can bestr
orNone
.
4. Type Hinting for Functions and Classes
a) Class Methods with Type Hints
class Person:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
def get_info(self) -> str:
return f"{self.name} is {self.age} years old."
person = Person("Alice", 30)
print(person.get_info()) # Output: Alice is 30 years old.
b) Self and ClassMethod Type Hinting
from typing import Type
class Animal:
def speak(self: "Animal") -> str:
return "Animal sound"
@classmethod
def create(cls: Type["Animal"]) -> "Animal":
return cls()
self: "Animal"
→ Refers to an instance ofAnimal
.cls: Type["Animal"]
→ Refers to the class type itself.
5. Type Hinting with Generics
Generics allow you to define flexible types that work with multiple data types.
from typing import TypeVar, List
T = TypeVar("T") # Generic type
def get_first_element(lst: List[T]) -> T:
return lst[0]
print(get_first_element([1, 2, 3])) # Output: 1
print(get_first_element(["A", "B"])) # Output: A
TypeVar("T")
→ Represents a generic type that can be replaced with any data type.
6. Callable Type Hinting (Functions as Arguments)
from typing import Callable
def apply_function(func: Callable[[int, int], int], x: int, y: int) -> int:
return func(x, y)
def multiply(a: int, b: int) -> int:
return a * b
print(apply_function(multiply, 3, 4)) # Output: 12
Callable[[int, int], int]
→ A function that takes twoint
arguments and returns anint
.
7. Type Hinting for Iterators and Generators
from typing import Iterator, Generator
def count_up(n: int) -> Iterator[int]:
for i in range(n):
yield i
def infinite_counter() -> Generator[int, None, None]:
num = 0
while True:
yield num
num += 1
Iterator[int]
→ Function returns an iterator yieldingint
values.Generator[int, None, None]
→ Function is a generator returningint
values.
8. Enforcing Type Hints at Runtime
Python does not enforce type hints by default, but you can use MyPy to check types.
Installing MyPy
pip install mypy
Running MyPy on a Python Script
mypy script.py
For example, running MyPy on this script:
def add_numbers(x: int, y: int) -> int:
return x + y
print(add_numbers(10, "20")) # TypeError
MyPy will catch the error:
error: Argument 2 to "add_numbers" has incompatible type "str"; expected "int"
9. Type Hinting in Python Versions
Python Version | Type Hinting Features |
---|---|
Python 3.5 | Introduced typing module (PEP 484) |
Python 3.6 | Variable annotations (PEP 526) |
Python 3.7 | from __future__ import annotations |
Python 3.8 | TypedDict for structured dicts |
Python 3.9 | Built-in generics (e.g., list[str] instead of List[str] ) |
Python 3.10 | Pattern matching, TypeGuard |
Python 3.11 | Performance improvements for type hints |