Type hints, dataclasses, async patterns, testing with pytest, and modern Python tooling
Perfect for:
Not ideal for:
from typing import Optional, List, Dict, Union, Callable, TypeVar, Generic
from collections.abc import Sequence, Mapping
# Function type hints
def process_items(items: List[str], count: int = 10) -> Dict[str, int]:
"""Process items and return counts."""
return {item: len(item) for item in items[:count]}
# Optional parameters
def get_user(user_id: int, default: Optional[str] = None) -> Optional[str]:
return default
# Union types (Python 3.10+ use |)
def handle_value(value: str | int | float) -> str:
return str(value)
# Callable types
def register_handler(callback: Callable[[int], str]) -> None:
result = callback(42)
# TypeVar for generics
T = TypeVar('T')
def get_first(items: List[T]) -> T:
return items[0]
# Type aliases
UserID = int
UserName = str
UserData = Dict[UserID, UserName]
from dataclasses import dataclass, field
from typing import List
@dataclass
class User:
"""User with type hints and validation."""
id: int
name: str
email: str
age: int = 0
tags: List[str] = field(default_factory=list)
def __post_init__(self):
"""Validate after initialization."""
if self.age < 0:
raise ValueError("Age cannot be negative")
# Usage
user = User(id=1, name="Alice", email="[email protected]", age=30)
print(user) # User(id=1, name='Alice', email='[email protected]', age=30, tags=[])
from pydantic import BaseModel, Field, field_validator
class User(BaseModel):
"""User model with validation."""
id: int
name: str = Field(..., min_length=1, max_length=100)
email: str = Field(..., pattern=r'^[\w\.-]+@[\w\.-]+\.\w+$')
age: int = Field(default=0, ge=0, le=150)
tags: list[str] = Field(default_factory=list)
@field_validator('name')
def name_must_be_titlecase(cls, v):
if not v.istitle():
raise ValueError('Name must be title case')
return v
class Config:
json_schema_extra = {
"example": {
"id": 1,
"name": "John Doe",
"email": "[email protected]",
"age": 30,
"tags": ["admin", "user"]
}
}
# Usage with validation