Complex Collection Typing
Advanced Collection Type Annotations
Complex collection typing allows developers to create sophisticated type hints for nested and intricate data structures, providing enhanced type safety and code clarity.
Nested Collections
from typing import List, Dict, Tuple, Set
## Nested list of integers
matrix: List[List[int]] = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
## Dictionary with complex value types
user_scores: Dict[str, List[int]] = {
'Alice': [85, 90, 92],
'Bob': [78, 85, 80]
}
Advanced Typing Techniques
1. Union Types
from typing import Union, List
## Mixed type collections
mixed_list: List[Union[int, str]] = [1, 'hello', 2, 'world']
def process_mixed_data(data: Union[int, str, List[int]]) -> str:
if isinstance(data, list):
return f"List with {len(data)} elements"
return str(data)
2. Optional and Nested Types
from typing import Optional, Dict, List
## Complex nested dictionary with optional values
complex_data: Dict[str, Optional[List[Dict[str, int]]]] = {
'users': [
{'id': 1, 'score': 95},
{'id': 2, 'score': 88}
],
'archived': None
}
Type Annotation Visualization
graph TD
A[Complex Collection Typing] --> B[Nested Collections]
A --> C[Advanced Type Hints]
A --> D[Specialized Typing]
B --> E[Nested Lists]
B --> F[Nested Dictionaries]
C --> G[Union Types]
C --> H[Optional Types]
D --> I[Generic Types]
D --> J[Custom Type Hints]
Generics and Custom Types
from typing import TypeVar, Generic, List
## Generic type variable
T = TypeVar('T')
## Generic collection class
class Stack(Generic[T]):
def __init__(self):
self.items: List[T] = []
def push(self, item: T) -> None:
self.items.append(item)
def pop(self) -> T:
return self.items.pop()
## Usage
int_stack: Stack[int] = Stack()
int_stack.push(10)
Type Checking Strategies
Strategy |
Description |
Use Case |
Static Type Checking |
Compile-time type verification |
Large projects |
Runtime Type Checking |
Dynamic type validation |
Critical systems |
Gradual Typing |
Partial type annotations |
Incremental adoption |
Complex Typing Patterns
from typing import Callable, Dict, Any
## Function type annotation
def apply_operation(
data: List[int],
operation: Callable[[int], int]
) -> List[int]:
return [operation(x) for x in data]
## Higher-order function typing
def create_transformer() -> Callable[[Dict[str, Any]], Dict[str, Any]]:
def transform(data: Dict[str, Any]) -> Dict[str, Any]:
return {k.upper(): v for k, v in data.items()}
return transform
- Type annotations have minimal runtime overhead
- Static type checking occurs before execution
- Improves code readability and maintainability
LabEx Insights
At LabEx, we recommend mastering complex collection typing to create more robust and self-documenting Python code. Understanding these advanced typing techniques can significantly improve your development workflow.
Best Practices
- Use precise type hints
- Leverage generic types
- Combine type annotations with runtime checks
- Use type checkers like mypy
- Document complex type structures