Зачем документировать и что такое docstring
Вы когда-нибудь открывали свой старый код через полгода и думали: «Кто это написал? Что это вообще делает?» Спойлер: это написали вы. В этом уроке разберёмся, как писать код, который будет понятен — и вам, и коллегам — через месяц, год и навсегда.
📖 Главный принцип: код читают чаще, чем пишут
Когда начинаешь программировать, кажется, что написать код — это самое главное. Нажал Run — работает, задача выполнена. Но в реальной разработке всё немного иначе.
По опыту профессиональных разработчиков: на каждую строку, которую пишут, приходится в 10 раз больше прочтений этой строки. Кто-то ищет баг, кто-то разбирается как работает функция, кто-то добавляет новую возможность — все они читают ваш код.
«Программы должны писаться для людей,
и лишь изредка — для компьютеров.»
— Харольд Абельсон, один из авторов классической книги SICP
Компьютеру всё равно, как вы назвали переменную и есть ли у функции описание. Он выполняет инструкции — и точка. Зато человеку, который будет читать ваш код через три месяца, совсем не всё равно.
⚠️ Важно понять прямо сейчас: документирование кода — это не бюрократия и не формальность. Это профессиональная забота о людях, которые будут читать ваш код. В первую очередь — о себе самом в будущем.
🧠 «Будущий ты через полгода — это другой человек»
Это звучит немного философски, но это правда. Давайте разберёмся почему.
📅 Типичная ситуация
Сентябрь: вы пишете функцию для расчёта скидки. Вы только что придумали алгоритм, у вас в голове всё ясно — зачем писать объяснение к очевидным вещам?
Март следующего года: вы открываете тот же файл. У вас за плечами ещё шесть месяцев опыта, десятки новых проектов, сотни других функций. Тот контекст из сентября — полностью вымыт из памяти. И вы смотрите на свой код как на чужой.
Посмотрите на простой пример. Угадайте, что делает эта функция:
def calc(x, y, z):
return x * (1 - y / 100) if z else x
Что такое x? Что такое y? Что такое z? Когда возвращается x, а когда x * (1 - y / 100)? Чтобы понять — нужно читать весь код вокруг, искать где функция вызывается...
А теперь посмотрите на ту же функцию, но с документацией:
def apply_discount(price, discount_percent, is_sale):
"""
Применяет скидку к цене товара.
Если товар участвует в акции (is_sale=True),
возвращает цену с учётом скидки.
Иначе возвращает исходную цену без изменений.
"""
return price * (1 - discount_percent / 100) if is_sale else price
Мгновенно понятно! Хорошее имя функции + докстринг — и никаких вопросов. Код говорит сам за себя.
👥 Командная разработка: твой код будут читать коллеги
Если вы работаете в команде — документирование становится ещё важнее. Ваш коллега не знает, что у вас было в голове, когда вы писали функцию. У него нет вашего контекста.
🔍
Онбординг нового разработчика
Новый человек в команде разбирается с проектом. Хорошие docstring'и — это самая быстрая документация: он открывает функцию и сразу видит, что она делает.
🐛
Поиск бага
Коллега ищет ошибку в вашем коде. Без docstring он тратит часы на разбор алгоритма. С docstring — видит намерение и быстро находит расхождение между «что должно быть» и «что есть».
🔧
Code review
Ревьюер проверяет ваш код перед тем, как он попадёт в основную ветку. Docstring помогает ему понять задумку, а не только реализацию — это делает ревью быстрее и точнее.
📚
Автоматическая документация
Инструменты вроде Sphinx берут docstring'и прямо из кода и генерируют красивую HTML-документацию. Написал docstring — получил документацию бесплатно.
💼 Профессиональная культура: в серьёзных компаниях отсутствие docstring в публичных методах — это замечание на code review. Так же, как опечатка в резюме: технически не критично, но говорит о небрежности.
📝 Что такое docstring — строка-документация
Docstring (от англ. documentation string — строка документации) — это специальная строка, которую вы пишете сразу после объявления функции, метода, класса или модуля.
Ключевое слово здесь — «сразу после». Docstring — это не просто комментарий в произвольном месте. Это первая строка тела функции/класса/модуля. Именно это место делает её особенной — Python сам сохраняет её как часть объекта.
🗝️ Где можно писать docstring
- В начале функции — после
def имя_функции(...): - В начале метода класса — точно так же, после
def - В начале класса — после
class ИмяКласса: - В самом начале модуля (файла .py) — самая первая строка файла
✍️ Синтаксис: тройные кавычки """..."""
Docstring записывается в тройных кавычках — либо двойных """...""", либо одинарных '''...'''. В Python принято использовать двойные.
Тройные кавычки нужны потому, что docstring может быть многострочным — тройные кавычки позволяют написать текст на нескольких строках без дополнительных символов.
Однострочный docstring — когда описание помещается в одну строку:
def greet(name):
"""Возвращает приветственное сообщение для пользователя."""
return f"Привет, {name}!"
Многострочный docstring — когда нужно описать подробнее:
def calculate_area(width, height):
"""
Вычисляет площадь прямоугольника.
Принимает ширину и высоту в сантиметрах.
Возвращает площадь в квадратных сантиметрах.
"""
return width * height
📐 Соглашение по форматированию (PEP 257)
- Однострочный: открывающие и закрывающие
"""на одной строке, точка в конце - Многострочный: первая строка — краткое описание, потом пустая строка, потом подробности, закрывающие
"""на отдельной строке - Текст внутри
"""пишут с большой буквы
🔬 Атрибут __doc__ — docstring живёт в объекте
Вот что делает docstring особенным — Python не просто «читает» эту строку и забывает. Он сохраняет её как атрибут объекта под именем __doc__. Это значит, что вы можете получить docstring в любой момент во время работы программы!
Двойные подчёркивания с обеих сторон (__doc__) — это в Python признак «магического» или «специального» атрибута. Такие атрибуты Python создаёт и использует сам. __doc__ — один из них.
def greet(name):
"""Возвращает приветственное сообщение для пользователя."""
return f"Привет, {name}!"
# Получаем docstring через атрибут __doc__
print(greet.__doc__)
# Вывод: Возвращает приветственное сообщение для пользователя.
class Dog:
"""Класс, описывающий собаку с именем и породой."""
def bark(self):
"""Заставляет собаку лаять."""
return "Гав!"
# Docstring доступен и у класса, и у его методов
print(Dog.__doc__)
# Вывод: Класс, описывающий собаку с именем и породой.
print(Dog.bark.__doc__)
# Вывод: Заставляет собаку лаять.
🧩 Запомните: docstring — это не просто текст в коде. Это часть объекта. Функция greet — это объект, и у неё есть атрибут __doc__ со значением «Возвращает приветственное сообщение...». Точно так же, как у неё есть имя (greet.__name__).
📦 Docstring для класса и модуля
Docstring пишут не только для функций. Классы и целые файлы (модули) тоже документируют. Посмотрим на полный пример:
"""
Модуль для работы с банковскими счетами.
Содержит класс BankAccount с методами для пополнения,
снятия и проверки баланса.
"""
class BankAccount:
"""
Банковский счёт с базовыми операциями.
Позволяет хранить баланс и выполнять
операции пополнения и снятия средств.
"""
def __init__(self, owner, balance=0):
"""
Создаёт новый банковский счёт.
owner — имя владельца счёта (строка)
balance — начальный баланс (число, по умолчанию 0)
"""
self.owner = owner
self.balance = balance
def deposit(self, amount):
"""Пополняет счёт на указанную сумму. Возвращает новый баланс."""
self.balance += amount
return self.balance
def withdraw(self, amount):
"""
Снимает деньги со счёта.
Если средств недостаточно, вызывает ValueError.
Возвращает новый баланс при успехе.
"""
if amount > self.balance:
raise ValueError("Недостаточно средств")
self.balance -= amount
return self.balance
Теперь доступ к документации:
import bank # представим, что файл называется bank.py
print(bank.__doc__)
# Модуль для работы с банковскими счетами...
print(BankAccount.__doc__)
# Банковский счёт с базовыми операциями...
print(BankAccount.withdraw.__doc__)
# Снимает деньги со счёта...
🆘 Функция help() — удобный просмотр docstring
Python предоставляет встроенную функцию help(), которая показывает документацию объекта в красивом, читаемом виде. Именно из __doc__ атрибута она берёт информацию.
Вы можете вызвать help() прямо в интерпретаторе Python или в Jupyter Notebook — это очень удобно при изучении незнакомого кода.
def apply_discount(price, discount_percent, is_sale):
"""
Применяет скидку к цене товара.
Параметры:
price — исходная цена (число)
discount_percent — размер скидки в процентах (число от 0 до 100)
is_sale — участвует ли товар в акции (True/False)
Возвращает цену с учётом скидки, если is_sale=True.
Иначе возвращает исходную цену без изменений.
"""
return price * (1 - discount_percent / 100) if is_sale else price
# Вызываем help() в интерпретаторе:
help(apply_discount)
Вывод в интерпретаторе будет выглядеть вот так:
Help on function apply_discount in module __main__:
apply_discount(price, discount_percent, is_sale)
Применяет скидку к цене товара.
Параметры:
price — исходная цена (число)
discount_percent — размер скидки в процентах (число от 0 до 100)
is_sale — участвует ли товар в акции (True/False)
Возвращает цену с учётом скидки, если is_sale=True.
Иначе возвращает исходную цену без изменений.
💡 Попробуйте прямо сейчас: в интерпретаторе Python напишите help(print) или help(len) — и увидите docstring встроенных функций. Именно так работает вся документация стандартной библиотеки Python.
⚖️ Docstring vs комментарий — в чём разница
В Python есть два способа оставить текстовое пояснение к коду: комментарий через # и docstring через """...""". Многие новички считают их одинаковыми — но между ними принципиальная разница.
# Комментарий
- Начинается с символа
# - Python полностью игнорирует его при выполнении
- Не сохраняется нигде — «испаряется»
- Недоступен через
__doc__илиhelp() - Используется для пояснения как работает конкретная строка кода
- Пишется в произвольном месте
"""Docstring"""
- Тройные кавычки
""" - Python сохраняет как атрибут
__doc__ - Живёт внутри объекта всё время работы программы
- Доступен через
obj.__doc__иhelp(obj) - Описывает что делает функция/класс/модуль
- Только первая строка тела объявления
Смотрите на примере — как они живут вместе:
def calculate_tax(price, rate):
"""Вычисляет сумму налога для заданной цены и ставки."""
# rate — это процент, поэтому делим на 100
# например rate=20 означает НДС 20%
return price * rate / 100
# Docstring сохранён и доступен:
print(calculate_tax.__doc__)
# Вывод: Вычисляет сумму налога для заданной цены и ставки.
# А комментарии — нет, они исчезли при выполнении:
# print(calculate_tax.comments) <-- такого атрибута не существует
🎯 Простое правило для запоминания:
Комментарий (#) — объясняет как работает этот кусок кода. Для разработчиков, читающих исходник.
Docstring (""") — объясняет что делает функция/класс. Для пользователей API, IDE и инструментов документации.
✅ Где обязательно писать docstring
Docstring — это хороший тон, но не всегда обязательный. Вот чёткое правило: если что-то «публичное» (то есть предназначено для использования другими), — docstring обязателен.
Публичные классы
Любой класс, который вы ожидаете использовать — сами или другие. Docstring объясняет, для чего класс существует.
Публичные методы и функции
Все методы без подчёркивания в начале имени. Имена вида calculate(), save(), get_price() — публичные. Каждый должен иметь docstring.
Модули (файлы .py)
Первые строки файла — коротко: что находится в этом модуле, какую задачу он решает. Особенно важно для библиотек и пакетов.
Приватные методы (опционально)
Методы с одним подчёркиванием _helper() — предназначены для внутреннего использования. Docstring желателен, но не обязателен. Если логика сложная — пишите.
📋 Практическое правило
Задайте себе вопрос: «Если кто-то вызовет эту функцию/создаст этот класс — ему нужно что-то знать кроме имени?» Если да — пишите docstring. Функция add(a, b) очевидна. Функция normalize_score(value, context) — требует объяснения.
✅ Итоги урока
- Код читается чаще, чем пишется — пишите для людей: для коллег, для себя будущего, для тех, кто будет поддерживать ваш код.
- «Будущий ты через полгода — другой человек»: без документации вы сами не поймёте свой код через несколько месяцев.
- Docstring — это строка в тройных кавычках
"""...""", которая пишется сразу после объявления функции, класса или модуля. - Атрибут
__doc__: Python сохраняет docstring как часть объекта — его можно прочитать в любой момент черезobj.__doc__. help(obj)показывает docstring в красивом виде — именно так работает документация стандартной библиотеки Python.- Docstring ≠ комментарий: комментарий (#) исчезает при выполнении, docstring живёт в объекте. Комментарий объясняет как, docstring объясняет что.
- Писать docstring обязательно для всех публичных классов, методов и функций — это профессиональный стандарт.
👉 В следующем уроке мы познакомимся с форматом Google Style docstring — наиболее популярным соглашением в современном Python-коде. Вы научитесь описывать параметры, возвращаемые значения и исключения так, как это делают в Google, Яндексе и других крупных компаниях.