Стандарты оформления docstring в Python: пишем понятную документацию
Для кого эта статья:
- Python-разработчики, желающие улучшить качество своего кода
- Студенты и новички в программировании, изучающие стандарты написания кода
Руководители команд разработки, заинтересованные в повышении эффективности работы группы
Код на Python как открытая книга — прочитать может каждый, но извлечь из неё пользу могут лишь те, кто разбирается в авторском стиле. Подобно тому, как литературные произведения имеют предсказуемую структуру, Python-код также должен следовать определенным конвенциям, особенно когда речь идет о документировании кода. Именно docstring и стандарты PEP превращают бессистемный набор функций в удобочитаемый, профессиональный код, который становится понятным с первого взгляда и не требует дополнительных усилий для расшифровки. 📚
Если вы хотите писать код, который не вызовет рвотного рефлекса у коллег на код-ревью, стоит освоить стандарты документирования в Python. На курсе Обучение Python-разработке от Skypro вы не только научитесь писать чистый код, но и поймете, как правильно его документировать согласно стандартам PEP 8 и PEP 257. Именно этот навык отличает профессионала от новичка и повышает вашу ценность как специалиста.
Что такое docstring и зачем нужны стандарты в Python
Docstring (сокращение от "documentation string") — это строка документации, которая служит для описания модулей, классов, функций и методов в Python. Она размещается сразу после объявления и перед телом кода, заключённая в тройные кавычки, что делает её многострочной по умолчанию.
Но зачем тратить время на написание документации, когда можно просто писать код? 🤔 Причина проста: код пишется один раз, а читается многократно — как вами, так и другими разработчиками.
Алексей Смирнов, технический лид в команде разработки
Как-то раз мы унаследовали проект от команды, которая полностью игнорировала docstrings. Я потратил почти две недели, разбираясь в кодовой базе размером примерно в 30 000 строк. Функции с неочевидными названиями вроде
process_dataилиhandle_exceptionбез документации превращались в настоящие головоломки. После этого кейса я ввёл в команде правило: код без docstring не проходит ревью. За три месяца производительность выросла на 30%, а количество багов снизилось вдвое — просто потому, что все стали лучше понимать, что и как работает.
Стандарты документирования в Python решают несколько ключевых проблем:
- Снижение когнитивной нагрузки — не нужно "держать в голове" всю логику кода
- Единообразие — одинаковый формат документации делает работу предсказуемой
- Автоматизация — docstrings используются для генерации документации инструментами вроде Sphinx
- Интеграция в IDE — современные редакторы показывают docstring при наведении на функцию
Согласно исследованию Stack Overflow, более 70% разработчиков тратят больше времени на чтение существующего кода, чем на написание нового. Именно поэтому стандарты документации — это не прихоть, а необходимость в профессиональной разработке.
| Характеристика | Код без docstring | Код с docstring |
|---|---|---|
| Время на понимание нового кода | В среднем 2-3 часа | 30-60 минут |
| Скорость онбординга новых сотрудников | 2-3 недели | 1-1.5 недели |
| Количество уточняющих вопросов | Высокое | Низкое |
| Возможность автоматической генерации документации | Отсутствует | Есть |

Основные требования PEP 257 для оформления документации
PEP 257 — это документ, который определяет стандарты для написания docstring в Python. Разработанный Гвидо ван Россумом, Барри Варшавом и Дэвидом Гудгером, этот стандарт устанавливает базовые правила, которые должен соблюдать каждый Python-разработчик.
Основные требования PEP 257:
- Все публичные модули, функции, классы и методы должны иметь docstrings. Не-публичные методы могут обойтись и без них, но все равно должны иметь комментарии, описывающие их функциональность.
- Docstring должен быть понятным в качестве текстового сообщения. Пишите его так, будто объясняете функциональность коллеге за обедом.
- Однострочные docstrings должны быть действительно однострочными. Тройные кавычки открываются и закрываются на той же строке.
- Многострочные docstrings должны иметь резюме в первой строке, за которым следует пустая строка, а затем более подробное описание.
- Избегайте повторения имени функции/метода в docstring — это избыточно и усложняет чтение.
Вот пример правильного однострочного docstring:
def get_user_by_id(user_id):
"""Return user object for the given user ID."""
return db.query(User).filter(User.id == user_id).first()
И пример правильного многострочного docstring:
def calculate_tax(income, tax_rate=0.2):
"""Calculate tax amount based on income and tax rate.
Args:
income (float): Gross income amount.
tax_rate (float, optional): Tax rate as a decimal. Defaults to 0.2.
Returns:
float: Calculated tax amount.
Raises:
ValueError: If income is negative.
"""
if income < 0:
raise ValueError("Income cannot be negative")
return income * tax_rate
Важно помнить, что docstring должен обеспечивать достаточную информацию для использования функции или класса без необходимости заглядывать в исходный код. Это особенно важно для библиотек и API, где пользователи могут не иметь доступа к исходникам.
Популярные стили форматирования docstring: сравнение подходов
PEP 257 устанавливает лишь базовые правила для docstring, но не определяет конкретный формат структурирования информации внутри документации. Именно поэтому в сообществе Python сформировались несколько популярных стилей, каждый со своими особенностями. 🔍
| Стиль | Особенности | Популярность | Подходит для |
|---|---|---|---|
| Google style | Секции выделяются заголовками, аргументы описываются в формате "name (type): description" | Очень высокая | Большинство проектов, особенно с TensorFlow и другими Google-технологиями |
| NumPy style | Расширение Google style с более подробным форматированием для научных проектов | Высокая в научной среде | Научные вычисления, анализ данных, проекты с NumPy/SciPy/Pandas |
| reStructuredText (reST) | Использует специальные директивы Sphinx, более формальный синтаксис | Средняя | Проекты с генерацией документации Sphinx, многие стандартные библиотеки Python |
| Epytext | Формат, подобный JavaDoc | Низкая | Устаревшие проекты |
Рассмотрим примеры трёх наиболее распространённых стилей для одной и той же функции:
1. Google style:
def connect_to_database(host, port=5432, user=None, password=None):
"""Establishes connection to PostgreSQL database.
Args:
host (str): Database server hostname or IP address.
port (int, optional): Port number. Defaults to 5432.
user (str, optional): Username for authentication. If None, uses system user.
password (str, optional): Password for authentication.
Returns:
Connection: Database connection object.
Raises:
ConnectionError: If connection cannot be established.
"""
2. NumPy style:
def connect_to_database(host, port=5432, user=None, password=None):
"""Establishes connection to PostgreSQL database.
Parameters
----------
host : str
Database server hostname or IP address.
port : int, optional
Port number. Default is 5432.
user : str, optional
Username for authentication. If None, uses system user.
password : str, optional
Password for authentication.
Returns
-------
Connection
Database connection object.
Raises
------
ConnectionError
If connection cannot be established.
"""
3. reStructuredText (reST):
def connect_to_database(host, port=5432, user=None, password=None):
"""Establishes connection to PostgreSQL database.
:param host: Database server hostname or IP address.
:type host: str
:param port: Port number, defaults to 5432
:type port: int, optional
:param user: Username for authentication, if None uses system user
:type user: str, optional
:param password: Password for authentication
:type password: str, optional
:returns: Database connection object
:rtype: Connection
:raises ConnectionError: If connection cannot be established
"""
Какой стиль выбрать? Это зависит от нескольких факторов:
- Google style обеспечивает хороший баланс между читаемостью и информативностью
- NumPy style предпочтителен для научных проектов с математическими формулами
- reStructuredText лучше интегрируется с инструментами Sphinx
Наталья Петрова, руководитель отдела обеспечения качества кода
В нашем проекте мы начинали без единого стандарта документации. Каждый писал docstrings, как привык. Когда команда выросла до 15 человек, у нас образовалось четыре разных стиля в одной кодовой базе! На ревью кода тратилось неоправданно много времени.
Мы провели голосование и выбрали Google style как наиболее интуитивно понятный. Затем настроили линтеры и внедрили автоматическую проверку при коммитах. Результат превзошёл ожидания: время на ревью сократилось на 40%, а количество вопросов между разработчиками уменьшилось почти на 70%. Главное, что мы вынесли из этого опыта: важен не столько выбор конкретного стиля, сколько его последовательное применение во всей кодовой базе.
PEP 8: правила оформления заголовков функций и классов
Если PEP 257 регламентирует стандарты документирования, то PEP 8 — это руководство по стилю кодирования Python, включающее правила именования и оформления заголовков функций, классов и других элементов кода. Эти стандарты неразрывно связаны с docstring, формируя полноценный профессиональный подход к разработке. 🛠️
Основные правила PEP 8 для заголовков функций и классов:
- Имена функций: Используйте snake_case (слова в нижнем регистре, разделённые подчёркиваниями)
- Имена классов: Используйте CamelCase (каждое слово с заглавной буквы, без разделителей)
- Имена констант: Используйте UPPERSNAKECASE (все заглавные буквы, разделённые подчёркиваниями)
- Приватные методы/атрибуты: Начинайте с одного подчёркивания (methodname)
- "Очень приватные" методы/атрибуты: Начинайте с двух подчёркиваний (_methodname)
- Магические методы: Окружайте двумя подчёркиваниями с обеих сторон (init)
Вот несколько примеров правильного именования по PEP 8:
# Функции
def calculate_average(numbers):
"""Return the average of a list of numbers."""
return sum(numbers) / len(numbers)
# Классы
class DatabaseConnection:
"""Class for managing database connections."""
def __init__(self, host, port):
"""Initialize connection with host and port."""
self.host = host
self.port = port
def _validate_credentials(self):
"""Internal method to validate credentials."""
pass
def __execute_raw_query(self, query):
"""Very private method for executing raw SQL queries."""
pass
# Константы
MAX_CONNECTION_ATTEMPTS = 3
DEFAULT_TIMEOUT = 30
Помимо именования, PEP 8 регламентирует и другие аспекты оформления заголовков:
- Расположение импортов: стандартная библиотека, сторонние библиотеки, локальные импорты — с пустыми строками между группами
- Количество пробелов: 4 пробела для отступов, без табуляций
- Максимальная длина строки: 79 символов для кода, 72 для docstring и комментариев
- Пустые строки: 2 между классами и функциями верхнего уровня, 1 между методами внутри класса
Соблюдение PEP 8 не просто делает код "красивым" — оно значительно упрощает чтение и понимание кода другими разработчиками, что критически важно в командных проектах.
Инструменты автоматизации проверки docstring-стандартов
Помнить все правила PEP 8 и PEP 257 — задача не из легких даже для опытного разработчика. К счастью, в экосистеме Python существует множество инструментов, которые автоматизируют проверку соответствия кода стандартам и помогают поддерживать высокое качество документации. 🤖
Основные инструменты для проверки docstring и форматирования кода:
- pylint — один из самых всеобъемлющих инструментов для статического анализа, который проверяет как соответствие PEP 8, так и наличие docstring
- flake8 — объединяет функциональность PyFlakes, pycodestyle и McCabe для комплексной проверки кода
- pydocstyle — специализированный инструмент для проверки соответствия docstring стандарту PEP 257
- black — бескомпромиссный форматтер кода, который автоматически приводит код к единому стилю
- docformatter — инструмент для автоматического форматирования docstring
- interrogate — проверяет уровень покрытия кода документацией
Пример настройки pre-commit хука для автоматизации проверки при коммите:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
- repo: https://github.com/pycqa/pydocstyle
rev: 6.3.0
hooks:
- id: pydocstyle
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
- repo: https://github.com/myint/docformatter
rev: v1.7.5
hooks:
- id: docformatter
- repo: https://github.com/econchick/interrogate
rev: 1.5.0
hooks:
- id: interrogate
args: [-vv, -i, --fail-under=80]
Интеграция этих инструментов в процесс разработки даёт множество преимуществ:
- Автоматизация рутинных проверок экономит время разработчиков
- Раннее обнаружение несоответствий стандартам предотвращает накопление технического долга
- Единообразие кода и документации упрощает поддержку проекта
- Новые участники команды быстрее адаптируются к принятым стандартам
Для интеграции этих инструментов с популярными IDE:
- PyCharm: Встроенная поддержка PEP 8 и возможность установки плагинов для других инструментов
- VSCode: Расширения Python и Python Docstring Generator обеспечивают поддержку стандартов и автоматическое создание docstring
- Jupyter Notebook: Расширение nbqa позволяет запускать инструменты проверки кода на ячейках Jupyter
Наиболее эффективный подход — настроить проверку на трёх уровнях:
- Локально: Интеграция с IDE для мгновенной обратной связи
- При коммите: Pre-commit хуки для предотвращения коммитов с нарушениями
- В CI/CD: Автоматизированные проверки при Pull Request и деплое
Качественно документированный код — это не роскошь, а необходимость в профессиональной разработке. Следование стандартам PEP 8 и PEP 257 при оформлении заголовков и docstring в Python существенно сокращает время на понимание кода, облегчает работу в команде и снижает количество ошибок. Внедрение автоматизированных инструментов проверки позволяет сделать этот процесс естественной частью рабочего потока. Помните: лучший код — это не только тот, который работает сегодня, но и тот, который будет понятен и через год.