Introduction
Python's typing module provides runtime support for type hints. Using TypeVar, Generic, Union, and Optional, we can create flexible and expressive type annotations.
TypeVar
from typing import TypeVar
T = TypeVar("T")
def first_element(lst: list[T]) -> T:
return lst[0]
numbers = [1, 2, 3]
first_num = first_element(numbers) # type: int
strings = ["a", "b", "c"]
first_str = first_element(strings) # type: str
Generic
from typing import Generic, TypeVar
T = TypeVar("T")
class Stack(Generic[T]):
def __init__(self):
self._items = []
def push(self, item: T):
self._items.append(item)
def pop(self) -> T:
return self._items.pop()
def peek(self) -> T:
return self._items[-1]
int_stack = Stack[int]()
int_stack.push(42)
Union
from typing import Union
def process(data: Union[str, bytes]) -> str:
if isinstance(data, bytes):
return data.decode("utf-8")
return data
result = process("hello")
result = process(b"hello")
Optional
from typing import Optional
def find_user(user_id: int) -> Optional[dict]:
if user_id > 0:
return {"id": user_id, "name": "User"}
return None
user = find_user(1)
user = find_user(0) # None
Complex Type Hints
from typing import Dict, List, Tuple, Callable, Any
def process_data(
items: List[Dict[str, Any]],
transformer: Callable[[int], str],
options: Dict[str, Tuple[bool, int]]
) -> List[str]:
pass
# Or using TypeVar for constraints
T = TypeVar("T", bound=Comparable)
def max_value(a: T, b: T) -> T:
return a if a > b else b
Practice Problems
- Create a Generic container class
- Use TypeVar with bounds
- Implement Union type handling
- Add Optional to function signatures
- Create Callable type annotations