🐍 Что это
Этот навык — сборник идиоматических шаблонов и лучших практик Python, от базовых до продвинутых. Он помогает писать Pythonic код: лаконичный, безопасный по типам, эффективный по памяти и легко поддерживаемый. Охватывает все основные механизмы языка: протоколы, dataclass-ы, контекстные менеджеры, генераторы, декораторы, асинхронность, подсказки типов, внедрение зависимостей, структуру пакетов и обработку ошибок.
⚡ Как работает
Навык разбит на модули, каждый описывает конкретный паттерн с примерами кода и пояснениями.
📘 Протоколы (structural subtyping)
Protocol из typing позволяет реализовать утиную типизацию с аннотациями. Вместо наследования от абстрактного класса достаточно определить класс с методами нужной сигнатуры — он автоматически удовлетворяет протоколу.
from typing import Protocol
class Repository(Protocol):
def find_by_id(self, id: str) -> dict | None: ...
Любой класс, реализующий find_by_id и save, может использоваться там, где ожидается Repository. Это даёт гибкость без жёстких иерархий и упрощает тестирование.
🧩 Dataclass-ы как DTO
@dataclass автоматически генерирует __init__, __repr__, __eq__. Идеально для объектов-значений и DTO. frozen=True делает экземпляр неизменяемым. field(default_factory=list) задаёт сложные значения по умолчанию. Хорошо сочетается с type hints.
🔧 Контекстные менеджеры
Для управления ресурсами (файлы, соединения) используйте with. Два способа:
- Функция-генератор с
@contextmanager — простой и лаконичный.
- Класс с
__enter__ / __exit__ — больше контроля, например маршрутизация исключений.
Пример: транзакция БД — фиксация при успехе, откат при ошибке.
⚙️ Генераторы
Генераторы обрабатывают данные лениво, не загружая всё в память. yield возвращает одно значение за раз. Генераторные выражения в круглых скобках (x**2 for x in range(1e6)) — замена списковых включений для больших данных. Можно строить конвейеры: numbers = (x for x in range(100)) → evens = (x for x in numbers if x%2==0).
🎨 Декораторы
Декораторы функций (@wraps) расширяют поведение без изменения исходного кода (логирование, замер времени). Декораторы классов могут превращать класс в синглтон или добавлять методы. @wraps обязателен для сохранения метаданных.
🌐 Async/await
Для операций I/O-bound (сеть, файлы) используйте async def и await. asyncio.gather запускает задачи конкурентно. Асинхронные контекстные менеджеры (__aenter__/__aexit__) управляют подключениями. asyncio.run запускает верхнеуровневую корутину.
📝 Продвинутые подсказки типов
TypeVar, Generic для создания обобщённых классов (например, репозиторий, параметризованный типом сущности). ParamSpec и Concatenate для типобезопасных декораторов. В Python 3.10+ синтаксис str | int | None и match-case.
🔄 Внедрение зависимостей (DI)
Рекомендуется конструкторная инъекция: зависимости передаются через __init__. Это делает код тестируемым — можно подменить БД на мок. Типизированные зависимости улучшают самодокументированность.
📦 Структура пакета
Проект организуется в src/ с разделением на модули: domain/ (бизнес-логика), services/ (сервисы), infrastructure/ (внешние зависимости). __init__.py экспортирует публичное API через __all__. Тесты отдельно: tests/unit/, tests/integration/.
❌ Обработка ошибок
Собственные исключения наследуют от базового DomainError, что упрощает обработку. В Python 3.11+ except* обрабатывает группы исключений (ExceptionGroup), позволяя разбирать разные типы ошибок в одном блоке.
🏷️ Свойства (property)
@property создаёт вычисляемые атрибуты с контролем доступа. Геттер только для чтения, сеттер с валидацией (например, проверка email).
🧪 Функциональный стиль
Функции высшего порядка: pipe объединяет несколько функций в цепочку, применяя результат слева направо. Используйте functools.reduce для композиции. Пример: pipe(str.strip, str.lower, lambda s: s.replace(' ', '_')).
📌 Когда использовать
- Проектирование API библиотек или внутренних модулей — протоколы и типы.
- Асинхронные/конкурентные сервисы — async/await, контекстные менеджеры.
- Обработка больших данных — генераторы, ленивые вычисления.
- Структурирование кодовой базы — dataclass-ы, DI, иерархия пакетов.
- Рефакторинг легаси — постепенно вводить протоколы, декораторы, type hints.
- Написание чистого Pythonic кода — следовать идиомам языка.
💡 Важно знать
- Используйте
Protocol вместо абстрактных классов, если не нужна разделяемая реализация.
- Для больших проектов логирование (
logging) предпочтительнее print.
- Type Hints не влияют на производительность — это подсказки для линтеров и IDE.
@wraps обязателен в декораторах, чтобы сохранить __name__, __doc__ и сигнатуру.
- Генераторные выражения одноразовые — не сохраняйте их, если нужно повторно итерировать.
- Для асинхронных БД-драйверов используйте async-контекстные менеджеры.
- При импорте модулей явно указывайте публичные имена в
__all__.
- Исключения лучше делать иерархическими: базовый класс приложения уточняется специализированными.
Комментарии
Комментариев пока нет. Будьте первым.