Docstrings, комментарии, README, changelog, документация API
Код говорит что делать, документация объясняет почему и как. Хорошая документация экономит часы отладки.
Хороший docstring включает:
# ❌ Плохо: нет docstring
def calculate_discount(price, discount):
return price * (1 - discount)
# ❌ Плохо: бесполезный docstring
def calculate_discount(price, discount):
"""Calculates discount.""" # Это очевидно из названия
return price * (1 - discount)
# ✅ Хорошо: подробный docstring
def calculate_discount(price: float, discount: float) -> float:
"""
Рассчитывает цену после применения скидки.
Args:
price: Исходная цена (должна быть положительной)
discount: Размер скидки от 0 до 1 (0.1 = 10%)
Returns:
Цена после применения скидки
Raises:
ValueError: Если price <= 0 или discount вне диапазона [0, 1]
Examples:
>>> calculate_discount(100, 0.1)
90.0
>>> calculate_discount(200, 0.25)
150.0
"""
if price <= 0:
raise ValueError("Price must be positive")
if not 0 <= discount <= 1:
raise ValueError("Discount must be between 0 and 1")
return price * (1 - discount)Google Style (рекомендуется для Python):
def fetch_user(user_id: int) -> dict:
"""
Получает данные пользователя из API.
Args:
user_id: Уникальный идентификатор пользователя
Returns:
Словарь с данными пользователя:
- id: int
- name: str
- email: str
Raises:
UserNotFoundError: Если пользователь не найден
APIError: При ошибке сетевого запроса
"""NumPy Style:
def fetch_user(user_id: int) -> dict:
"""
Получает данные пользователя из API.
Parameters
----------
user_id : int
Уникальный идентификатор пользователя
Returns
-------
dict
Словарь с данными пользователя
Raises
------
UserNotFoundError
Если пользователь не найден
"""# ❌ Плохо: нет описания
class UserService:
def __init__(self, db):
self.db = db
def get_user(self, user_id):
...
# ✅ Хорошо: описание класса и методов
class UserService:
"""
Сервис для работы с пользователями.
Предоставляет методы для создания, получения и обновления
данных пользователей. Использует базу данных для хранения.
Attributes:
db: Подключение к базе данных
Examples:
>>> service = UserService(db)
>>> user = service.get_user(123)
"""
def __init__(self, db):
"""
Инициализирует сервис.
Args:
db: Активное подключение к базе данных
"""
self.db = db
def get_user(self, user_id: int) -> Optional[User]:
"""
Получает пользователя по ID.
Args:
user_id: Идентификатор пользователя
Returns:
Объект User или None если не найден
"""
...Объяснение «почему»:
# ✅ Хорошо: объясняет причину
# Используем линейный поиск вместо бинарного, так как
# список маленький (< 100 элементов) и не отсортирован
def find_user(users, target_id):
for user in users:
if user.id == target_id:
return user
return NoneПредупреждение о побочных эффектах:
# ✅ Хорошо: предупреждает о проблеме
# ВНИМАНИЕ: Эта функция модифицирует входной список
# Если нужна неизменяемость, используйте copy_list()
def sort_users_in_place(users):
users.sort(key=lambda u: u.name)TODO и HACK:
# ✅ Хорошо: временное решение с объяснением
# TODO: Заменить на кэширование с Redis при нагрузке > 1000 RPS
# HACK: Обход бага в библиотеке v1.2.3, удалить после обновления до v1.3.0
# FIXME: Утечка памяти при обработке больших файлов# ❌ Плохо: пересказывает код
# Проверяем, что пользователь активен
if user.is_active:
process(user)
# ❌ Плохо: очевидный комментарий
# Увеличиваем счётчик на 1
counter += 1
# ❌ Плохо: закомментированный мертвый код
# old_function() # Это больше не нужно
# another_old_call()# Название проекта
Краткое описание (1-2 предложения): что делает проект и зачем нужен.
## Установка
```bash
git clone https://github.com/user/project.git
cd project
pip install -r requirements.txtfrom myproject import MyClass
obj = MyClass()
result = obj.do_something()| Переменная | Описание | По умолчанию |
|---|---|---|
DATABASE_URL | URL базы данных | sqlite:///db.sqlite3 |
DEBUG | Режим отладки | False |
pytest tests/MIT
## 5. CHANGELOG
### Формат Keep a Changelog
```markdown
# Changelog
## [1.2.0] - 2024-03-07
### Добавлено
- Новая функция экспорта в CSV (#123)
- Поддержка Python 3.12
### Изменено
- Улучшена производительность импорта на 30%
### Исправлено
- Баг с кодировкой UTF-8 при экспорте (#145)
- Утечка памяти в фоновых задачах
### Удалено
- Устаревший API v1
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI(
title="My API",
description="API для управления пользователями",
version="1.0.0"
)
class UserCreate(BaseModel):
"""
Данные для создания пользователя.
Attributes:
username: Уникальное имя пользователя (3-50 символов)
email: Email адрес
password: Пароль (минимум 8 символов)
"""
username: str
email: str
password: str
@app.post("/users", response_model=User)
def create_user(user: UserCreate):
"""
Создаёт нового пользователя.
- **username**: Уникальное имя пользователя
- **email**: Email адрес
- **password**: Пароль
Returns:
Созданный объект пользователя
Raises:
HTTPException 400: Если email уже занят
HTTPException 422: Если данные невалидны
"""
...Ключевая мысль: Документация — это письмо будущему разработчику (которым можете быть вы через 6 месяцев). Пишите так, как будто от этого зависит ваша работа (потому что так и есть).
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.