Сегодня разберем тот случай, когда бизнес приходит с очередной задачей, звучащей так: «Нам нужно, чтобы награды для пользователей можно было гибко менять, подстраивать, проверять и, главное, не ломать всё при каждом чихе».
Pydantic — это библиотека для Python, которая превращает данные в нормальные структуры и валидирует их. В отличие от обычных dataclass'ов, он понимает, что данные редко бывают идеальными, и может ловить их на месте.
Например, вот классический кейс:
Пользователь совершил действие.
На сервер улетает JSON: «я убил дракона, дай мне 100 золотых».
Вы проверяете данные, создаете награду, отправляете пользователю.
Идея в том, чтобы не проверять такие данные вручную через if
'ы, а построить модель, которая сама все расскажет. И бонусом — чтобы вся логика не развалилась при следующем обновлении.
Простой пример: валидируем данные награды.
кОfrom pydantic import BaseModel, Field
class Reward(BaseModel):
type: str
amount: int = Field(..., gt=0, description="Количество награды (должно быть больше нуля)")
reward = Reward(type="gold", amount=100)
print(reward)
Код проверяет, что amount
больше нуля, а так же генерирует документацию для полей (например, description
). Если данные некорректны, бросает исключение.
Пример ситуации
Описываем типы наград
Будет три базовых типа наград:
Золото.
Очки опыта.
Скидки.
Каждый тип имеет свои уникальные параметры. Схема Pydantic для этого:
from typing import Union
from pydantic import BaseModel, Field
class GoldReward(BaseModel):
type: str = Field("gold", const=True)
amount: int = Field(..., gt=0, description="Количество золота")
class XPReward(BaseModel):
type: str = Field("xp", const=True)
points: int = Field(..., gt=0, description="Очки опыта")
class DiscountReward(BaseModel):
type: str = Field("discount", const=True)
percentage: float = Field(..., gt=0, lt=100, description="Скидка в процентах")
Reward = Union[GoldReward, XPReward, DiscountReward]
Проверяем данные
Допустим, система присылает JSON с наградой. Pydantic превращает его в объект Python.
reward_data = {"type": "gold", "amount": 150}
# Валидируем и преобразуем
try:
reward = Reward.parse_obj(reward_data)
print(reward)
except ValidationError as e:
print(f"Ошибка валидации: {e}")
Динамическая адаптация наград
Теперь сделаем адаптер, который меняет награду в зависимости от условий. Например:
VIP‑пользователи получают удвоенное золото.
Скидки выше 50% требуют дополнительного подтверждения.
class User(BaseModel):
id: int
is_vip: bool = False
class RewardAdapter:
def __init__(self, reward: Reward, user: User):
self.reward = reward
self.user = user
def adapt(self):
if isinstance(self.reward, GoldReward) and self.user.is_vip:
self.reward.amount *= 2
elif isinstance(self.reward, DiscountReward) and self.reward.percentage > 50:
print("Внимание: скидка требует одобрения!")
return self.reward
Пример использования:
user = User(id=42, is_vip=True)
reward_data = {"type": "gold", "amount": 100}
reward = Reward.parse_obj(reward_data)
adapter = RewardAdapter(reward, user)
adapted_reward = adapter.adapt()
print(adapted_reward)
Добавляем новые типы наград
Что если завтра появляется новый тип награды? Например, «бонусный доступ» к платным функциям. Достаточно просто добавить еще одну модель.
class AccessReward(BaseModel):
type: str = Field("access", const=True)
feature: str = Field(..., description="Название функции")
Reward = Union[GoldReward, XPReward, DiscountReward, AccessReward]
Покрываем тестами
Тесты спасают от сюрпризов. Покажу простой тест на VIP‑адаптацию:
def test_vip_gold_reward():
user = User(id=1, is_vip=True)
reward = GoldReward(type="gold", amount=100)
adapter = RewardAdapter(reward, user)
adapted = adapter.adapt()
assert adapted.amount == 200
Прочая информация
1. А как с безопасностью данных?
Pydantic позволяет строго ограничивать входные данные. Например:
Указываем диапазоны (
gt=0
,lt=100
).Используем
const=True
, чтобы запрещать некорректные типы.
2. Можно ли использовать Pydantic с FastAPI?
Да! FastAPI поддерживает Pydantic для описания запросов и ответов.
3. А если бизнес‑логика станет сложнее?
Добавляйте адаптеры для каждого нового условия. Pydantic позволяет строить вложенные схемы и обрабатывать их в адаптерах.
С прочими возможностями pydantic можно ознакомиться здесь.
17 декабря в рамках курса "Reinforcement Learning" пройдет открытый урок «Алгоритмы с подкреплением в стохастических играх». Узнать подробности и записаться можно по ссылке.