EasyТеория3 min

Документирование кода

Docstrings, стили документирования, pydoc, mkdocs и автоматическая документация

Документирование кода Python

Зачем документировать

Код пишется один раз, но читается многократно. Хорошая документация помогает новым разработчикам, служит контрактом для API и помогает вам через 6 месяцев.

Docstrings

Docstring — строковый литерал, стоящий первой инструкцией в модуле, классе или функции:

def calculate_bmi(weight_kg: float, height_m: float) -> float:
    """Calculate Body Mass Index (BMI).

    Args:
        weight_kg: Weight in kilograms. Must be positive.
        height_m: Height in meters. Must be positive.

    Returns:
        BMI value as float.

    Raises:
        ValueError: If weight or height is non-positive.

    Examples:
        >>> calculate_bmi(70, 1.75)
        22.857142857142858
    """
    if weight_kg <= 0 or height_m <= 0:
        raise ValueError("Weight and height must be positive")
    return weight_kg / (height_m ** 2)

# Access docstring
print(calculate_bmi.__doc__)
help(calculate_bmi)

Однострочные docstrings

def square(n: int) -> int:
    """Return the square of n."""
    return n * n

Стили документирования

Google Style (рекомендуемый)

class UserService:
    """Service for managing user accounts.

    Attributes:
        repository: User data repository.
        notifier: Notification service.
    """

    def create_user(self, name: str, email: str, role: str = "user") -> "User":
        """Create a new user account.

        Args:
            name: Full name, 1-100 characters.
            email: Email address. Must be unique.
            role: User role. Defaults to "user".

        Returns:
            Newly created User object with assigned ID.

        Raises:
            ValueError: If name is empty or email invalid.
            DuplicateError: If email already exists.
        """
        ...

NumPy/SciPy Style

def normalize(data: list[float], method: str = "minmax") -> list[float]:
    """Normalize a list of numerical values.

    Parameters
    ----------
    data : list[float]
        Input data. Must contain at least 2 values.
    method : str, optional
        Normalization method. Default is "minmax".

    Returns
    -------
    list[float]
        Normalized values.

    Examples
    --------
    >>> normalize([1, 2, 3, 4, 5])
    [0.0, 0.25, 0.5, 0.75, 1.0]
    """
    ...

Комментарии vs Docstrings

# Comments explain WHY (implementation details)
# Docstrings explain WHAT (public API contract)

class Cache:
    """In-memory LRU cache with TTL support."""

    def get(self, key: str) -> str | None:
        """Get value by key, or None if expired/missing."""
        # Check expiration first to avoid returning stale data
        if self._is_expired(key):
            del self._store[key]
            return None
        return self._store.get(key)

Когда НЕ нужны комментарии

# BAD: comment repeats the code
i += 1  # Increment i by 1

# GOOD: explains non-obvious decision
# Use binary search because the list is sorted and can have 1M+ elements
index = bisect.bisect_left(sorted_items, target)

# GOOD: explains business rule
# Free shipping for orders over 5000 (marketing decision Q1 2026)
if order.total >= 5000:
    order.shipping_cost = 0

Инструменты генерации документации

pydoc — встроенный

python -m pydoc json           # View in terminal
python -m pydoc myapp.utils
python -m pydoc -b             # Start local docs server

mkdocs + mkdocstrings

pip install mkdocs mkdocs-material mkdocstrings[python]
# mkdocs.yml
site_name: MyApp Documentation
theme:
  name: material
plugins:
  - search
  - mkdocstrings:
      handlers:
        python:
          options:
            docstring_style: google
<!-- docs/api/services.md -->
# Services API

::: myapp.services.UserService
mkdocs serve    # Dev server
mkdocs build    # Build static site

Type Hints как документация

from dataclasses import dataclass
from datetime import datetime
from enum import Enum

class OrderStatus(Enum):
    PENDING = "pending"
    CONFIRMED = "confirmed"
    SHIPPED = "shipped"
    DELIVERED = "delivered"

@dataclass
class Order:
    """Customer order.

    Attributes:
        id: Unique order identifier.
        customer_email: Customer's email.
        items: List of product names.
        total: Total price in rubles.
        status: Current order status.
    """
    id: int
    customer_email: str
    items: list[str]
    total: float
    status: OrderStatus = OrderStatus.PENDING
    created_at: datetime | None = None

Чеклист документирования

Что Документировать?
Публичные функции/классы Всегда (docstring)
Публичные модули Всегда
Приватные методы По необходимости
Нетривиальная логика Комментарий
Бизнес-правила Обязательно
Workaround/hack Обязательно + ссылка на issue
Очевидный код Не нужно

Проверь себя

Как получить docstring функции программно?

Какой стиль docstrings рекомендуется для большинства Python-проектов?

Чем комментарии отличаются от docstrings?

Какой инструмент генерирует документацию из docstrings и Markdown?