Python data structure conventions for this codebase. Apply when choosing between Pydantic models, dataclasses, and other data containers or reviewing data structure design choices.
Use Pydantic models or dataclasses instead of raw dictionaries or tuples.
| Use Case | Choice | Example |
|---|---|---|
| Validation, serialization, API boundaries | Pydantic BaseModel | Request/response models |
| Simple internal data containers | dataclass | Internal DTOs |
| Immutable value objects, hashable keys | dataclass(frozen=True) | Cache keys, IDs |
| Configuration from environment | Pydantic BaseSettings | App settings |
| Performance-critical hot paths | dataclass | Lower overhead than Pydantic |
| Pattern | Reason |
|---|
Raw dict returns | No IDE support, no validation, error-prone |
tuple returns | Positional access is unclear |
NamedTuple | Only for backward compatibility when refactoring tuple returns |
Use for validation, serialization, and API boundaries.
# CORRECT - Pydantic model with Field descriptions
from pydantic import BaseModel, Field
class SearchResult(BaseModel):
"""A single search result from the retrieval system."""
document_id: str = Field(description="Unique identifier for the document")
content: str = Field(description="The matched text content")
score: float = Field(ge=0.0, le=1.0, description="Relevance score")
metadata: dict[str, str] = Field(default_factory=dict)
# INCORRECT - raw dictionary
def search(query: str) -> dict: # No type safety, no validation
return {"id": "123", "content": "...", "score": 0.95}
ge, le, min_length, etc.)Use pydantic_settings.BaseSettings for environment-based configuration.
# CORRECT - typed settings from environment
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
"""Application settings loaded from environment."""
openai_api_key: str
database_url: str
debug: bool = False
max_workers: int = 4
model_config = {"env_prefix": "APP_"}
# Usage: reads APP_OPENAI_API_KEY, APP_DATABASE_URL, etc.
settings = Settings()
Use for simple internal data containers where validation isn't needed.
# CORRECT - simple dataclass
from dataclasses import dataclass
@dataclass
class Point:
"""A 2D point."""
x: float
y: float
# CORRECT - frozen for immutability and hashing
@dataclass(frozen=True)
class UserId:
"""Immutable user identifier, safe for use as dict key."""
value: int
# Can be used as dict key or in sets