$ sudo teach IT
МОДУЛЬ 10 · УРОК 2

Форматы docstring: Google Style, NumPy, reStructuredText

В прошлом уроке мы узнали, что такое docstring. Теперь разберёмся, как его правильно оформлять. В Python существует три главных формата — каждый со своими правилами записи. Разберём все три на одном и том же примере и решим, какой выбрать.

⏱ ~35 минут 🎓 Для новичков 🐍 Python 3

🤔 Зачем нужны форматы — разве тройных кавычек не достаточно?

Python требует только одного: docstring должен начинаться с тройных кавычек и стоять сразу после объявления функции или класса. Никаких правил о том, как именно писать содержимое внутри — в стандарте нет.

На практике это привело к тому, что каждый писал docstring по-своему. Параметры кто-то описывал через тире, кто-то в скобках, кто-то вообще не описывал. Чтение таких docstring'ов превращалось в квест.

Поэтому сообщество выработало соглашения — единые правила оформления. Главных три:

🟢

Google Style

Лаконичный и читаемый. Самый популярный в современных проектах. Рекомендован для большинства случаев.

🔵

NumPy Style

Более развёрнутый и структурированный. Стандарт в научных библиотеках: NumPy, SciPy, pandas.

🟡

reStructuredText

Официальный формат PEP 287. Используется в Sphinx для генерации документации. Многословен, но машинно читаем.

💡 Самое важное правило: не важно, какой формат вы выберете — важно использовать один и тот же формат во всём проекте. Смесь форматов в одном проекте — признак хаоса в команде.

🧪 Наша подопытная функция

Чтобы честно сравнить все три формата, мы возьмём одну и ту же функцию и запишем её docstring тремя способами. Вот наша функция:

def calculate_bmi(weight, height):
    if height <= 0:
        raise ValueError("Рост должен быть больше нуля")
    bmi = weight / (height ** 2)
    return round(bmi, 2)

📋 Что делает эта функция:

  • Принимает weight — вес человека в килограммах (число с плавающей точкой)
  • Принимает height — рост в метрах (число с плавающей точкой)
  • Вычисляет ИМТ (индекс массы тела) по формуле: вес / рост²
  • Возвращает результат, округлённый до 2 знаков после запятой
  • Вызывает ValueError, если рост равен нулю или отрицательный
Google Style

🟢 Формат Google Style

Google Style был разработан и популяризован компанией Google для внутренних Python-проектов. Сегодня это самый распространённый формат в современных open-source библиотеках и продуктовых командах.

Главная идея: секции обозначаются заголовком с двоеточием (Args:, Returns:, Raises:), а содержимое каждой секции пишется с отступом в 4 пробела.

def calculate_bmi(weight, height):
    """
    Вычисляет индекс массы тела (ИМТ) человека.

    Индекс массы тела — это число, которое показывает,
    соответствует ли вес человека его росту. Вычисляется
    по формуле: weight / height ** 2.

    Args:
        weight (float): Вес человека в килограммах.
            Должен быть положительным числом.
        height (float): Рост человека в метрах.
            Должен быть больше нуля.

    Returns:
        float: ИМТ, округлённый до 2 знаков после запятой.

    Raises:
        ValueError: Если height равен нулю или отрицателен.

    Example:
        >>> calculate_bmi(70, 1.75)
        22.86
        >>> calculate_bmi(90, 1.80)
        27.78
    """
    if height <= 0:
        raise ValueError("Рост должен быть больше нуля")
    bmi = weight / (height ** 2)
    return round(bmi, 2)

Разберём структуру по частям:

Первая строка

Краткое описание в одну строку. Отвечает на вопрос «что делает?». Заглавная буква, точка в конце.

Args:

Список параметров. Формат: имя (тип): описание. Если описание длинное — переносим на новую строку с двойным отступом.

Returns:

Описание возвращаемого значения. Формат: тип: описание.

Raises:

Исключения, которые может вызвать функция. Формат: ТипОшибки: когда возникает.

Example:

Примеры вызова функции в формате Python REPL (>>>). Показывает ожидаемый вывод.

✅ Плюсы Google Style

— Легко читается «глазами» — структура интуитивно понятна без знания формата
— Компактный: меньше символов на экране, не «раздувает» docstring
— Поддерживается популярными IDE (PyCharm, VS Code) и инструментом Napoleon для Sphinx

NumPy Style

🔵 Формат NumPy Style

NumPy Style разработан командой NumPy — одной из важнейших научных библиотек Python. Его используют NumPy, SciPy, pandas, scikit-learn и другие инструменты для науки о данных.

Главная идея: каждая секция обозначается заголовком, а под заголовком проводится горизонтальная черта из дефисов такой же длины, как заголовок. Параметры описываются более развёрнуто — тип пишется не в скобках, а на следующей строке.

def calculate_bmi(weight, height):
    """
    Вычисляет индекс массы тела (ИМТ) человека.

    Индекс массы тела — это число, которое показывает,
    соответствует ли вес человека его росту. Вычисляется
    по формуле: weight / height ** 2.

    Parameters
    ----------
    weight : float
        Вес человека в килограммах.
        Должен быть положительным числом.
    height : float
        Рост человека в метрах.
        Должен быть больше нуля.

    Returns
    -------
    float
        ИМТ, округлённый до 2 знаков после запятой.

    Raises
    ------
    ValueError
        Если height равен нулю или отрицателен.

    Examples
    --------
    >>> calculate_bmi(70, 1.75)
    22.86
    >>> calculate_bmi(90, 1.80)
    27.78
    """
    if height <= 0:
        raise ValueError("Рост должен быть больше нуля")
    bmi = weight / (height ** 2)
    return round(bmi, 2)

Обратите внимание на ключевые отличия от Google Style:

  • Секция называется Parameters (а не Args), и под ней идёт строка из дефисов: ----------
  • Тип параметра пишется через пробел после имени: weight : float
  • Описание параметра — на следующей строке с отступом
  • Секция возврата называется Returns, тип на отдельной строке, описание — ниже
  • Секция исключений называется Raises, тип на отдельной строке
  • Примеры — во множественном числе: Examples

✅ Плюсы и ⚠️ минусы NumPy Style

✅ Очень чёткая структура — легко сканировать взглядом при большом числе параметров
✅ Стандарт в научном сообществе — если вы пишете для DS/ML, это привычный формат
⚠️ Более многословный — занимает больше места, чем Google Style
⚠️ Строки из дефисов приходится рисовать вручную и поддерживать их длину

reST / Sphinx

🟡 Формат reStructuredText (Sphinx-style)

reStructuredText (сокращённо reST) — это язык разметки, созданный специально для документации Python. Именно его использует Sphinx — самая популярная система генерации документации. Официальный PEP 287 рекомендует reST как стандарт.

Главная идея: каждый элемент описывается отдельной директивой-тегом с двоеточиями: :param имя:, :type имя:, :return:, :rtype:, :raises ТипОшибки:. Никаких секций — каждый параметр описывается на своей строке.

def calculate_bmi(weight, height):
    """
    Вычисляет индекс массы тела (ИМТ) человека.

    Индекс массы тела — это число, которое показывает,
    соответствует ли вес человека его росту. Вычисляется
    по формуле: weight / height ** 2.

    :param weight: Вес человека в килограммах.
    :type weight: float
    :param height: Рост человека в метрах. Должен быть больше нуля.
    :type height: float
    :return: ИМТ, округлённый до 2 знаков после запятой.
    :rtype: float
    :raises ValueError: Если height равен нулю или отрицателен.

    Пример использования::

        >>> calculate_bmi(70, 1.75)
        22.86
    """
    if height <= 0:
        raise ValueError("Рост должен быть больше нуля")
    bmi = weight / (height ** 2)
    return round(bmi, 2)

Запомните эти теги — именно их распознаёт Sphinx и IDE:

:param имя:

Описание параметра функции. Один тег на каждый параметр.

:type имя:

Тип параметра. Идёт сразу после :param для того же параметра.

:return:

Описание возвращаемого значения.

:rtype:

Тип возвращаемого значения. Sphinx создаёт ссылку в документации.

:raises Тип:

Исключение и условие его возникновения.

✅ Плюсы и ⚠️ минусы reST

✅ Официальный стандарт Python — поддерживается Sphinx «из коробки»
✅ Машинно-читаемый — IDE и инструменты анализируют теги и дают подсказки
⚠️ Теги :param: / :type: выглядят многословно при чтении «глазами»
⚠️ При большом числе параметров docstring становится очень длинным
⚠️ Менее читаем для новичков без знания reST-разметки

⚖️ Сравнение форматов — таблица

Теперь посмотрим на три формата рядом, чтобы понять разницу наглядно.

Критерий Google Style NumPy Style reStructuredText
Читаемость ⭐⭐⭐⭐⭐ Отличная ⭐⭐⭐⭐ Хорошая ⭐⭐⭐ Средняя
Компактность ✅ Компактный ⚠️ Многословный ⚠️ Многословный
Поддержка Sphinx ✅ Через Napoleon ✅ Через Napoleon ✅ Нативная
Популярность 🔥 Очень высокая 📊 В DS/ML сфере 📘 Старые проекты
Порог входа ✅ Низкий ⚠️ Средний ⚠️ Средний
Лучше всего для Большинство проектов Научные библиотеки Sphinx-документация

📐 Структура хорошего docstring — универсальный шаблон

Независимо от выбранного формата, структура хорошего docstring всегда следует одному и тому же порядку. Это порядок закреплён в PEP 257 и является общепринятой практикой:

1

Краткое описание (Summary line)

Одна строка. Что делает функция/метод. Начинается с глагола: «Вычисляет...», «Возвращает...», «Преобразует...». Без точки в конце необязательно, но принято с точкой.

2

Пустая строка

Обязательная пустая строка после краткого описания. Именно это отделяет summary от деталей. PEP 257 требует её явно.

3

Расширенное описание (опционально)

Если одной строки недостаточно — здесь поясняем детали: алгоритм, ограничения, особенности поведения. Для простых функций этого раздела может не быть.

4

Args / Parameters

Список всех параметров с типами и описанием. Каждый параметр с новой строки. Пропускается, если у функции нет параметров.

5

Returns

Тип и смысл возвращаемого значения. Пропускается для функций, возвращающих None.

6

Raises

Все исключения, которые может явно вызвать функция. Каждое с объяснением — при каком условии.

7

Examples

Примеры вызова. Часто самая полезная часть — читатель сразу видит «живой» код. Примеры также можно запустить через doctest.

🎯 Не нужно писать все секции всегда. Простой функции без параметров достаточно одной строки. Секция Raises нужна только если функция что-то вызывает. Ориентируйтесь на полезность: docstring должен отвечать на вопросы читателя, а не быть «заполненной бюрократической формой».

🏆 Какой формат выбрать? Наша рекомендация

Вопрос не в том, какой формат «правильный» — все три правильные. Вопрос в том, какой подходит вашей ситуации.

✅ Для большинства проектов: Google Style

Если вы пишете веб-сервис, утилиту, API, автоматизацию или любой «обычный» Python-проект — используйте Google Style. Он читается легче всего, требует минимум «шаблонного» текста и поддерживается всеми современными инструментами.

🔵 Для Data Science и научных библиотек: NumPy Style

Если ваш проект связан с анализом данных, машинным обучением, и вы работаете с экосистемой NumPy/pandas/scikit-learn — используйте NumPy Style. Ваши коллеги из этой сферы привыкли именно к нему.

🟡 Для библиотек с HTML-документацией: reStructuredText

Если вы разрабатываете публичную библиотеку и хотите генерировать красивую HTML-документацию через Sphinx без дополнительных расширений — reST подойдёт лучше всего.

🚫 Главное правило — один формат в проекте

Не смешивайте форматы в одном проекте. Если в одном файле Google Style, а в другом NumPy — это хаос. Договоритесь с командой заранее, зафиксируйте в README или CONTRIBUTING.md и придерживайтесь этого всегда.

📌 Быстрый справочник — ключевые секции

Шпаргалка: одни и те же элементы в трёх форматах.

# Параметры

# Google Style:
# Args:
#     name (type): описание.

# NumPy Style:
# Parameters
# ----------
# name : type
#     описание.

# reStructuredText:
# :param name: описание.
# :type name: type


# Возвращаемое значение

# Google Style:
# Returns:
#     type: описание.

# NumPy Style:
# Returns
# -------
# type
#     описание.

# reStructuredText:
# :return: описание.
# :rtype: type


# Исключения

# Google Style:
# Raises:
#     ValueError: когда возникает.

# NumPy Style:
# Raises
# ------
# ValueError
#     когда возникает.

# reStructuredText:
# :raises ValueError: когда возникает.

✅ Итоги урока

  • Три главных формата: Google Style, NumPy Style и reStructuredText — каждый со своим синтаксисом секций.
  • Google Style использует заголовки с двоеточием (Args:, Returns:, Raises:) и отступы — лаконичный и читаемый.
  • NumPy Style использует заголовок и строку дефисов под ним, тип и описание параметра на отдельных строках — подробный и структурированный.
  • reStructuredText использует теги-директивы (:param:, :type:, :return:, :rtype:, :raises:) — официальный формат Sphinx.
  • Структура docstring: краткое описание → пустая строка → детали → Args → Returns → Raises → Examples.
  • Рекомендация: для большинства проектов используйте Google Style — он популярнее всего и легче читается.
  • Железное правило: один формат на весь проект. Смешивать форматы — недопустимо.

👉 В следующем уроке мы познакомимся с type hints — аннотациями типов в Python. Вы узнаете, как совмещать аннотации типов и docstring, чтобы ваш код был максимально понятным и помогал IDE находить ошибки ещё до запуска программы.