Ответ
Декоратор @computed_field в Pydantic (начиная с v2) используется для создания вычисляемых полей, значения которых генерируются на основе других полей модели. Эти поля не являются частью входных данных, но включаются в результат сериализации (например, при вызове .model_dump()).
Основные области применения:
- Производные данные: Создание полей, которые являются результатом вычислений над другими полями (например,
full_nameизfirst_nameиlast_name). - Агрегация: Вычисление итоговых значений, таких как общая стоимость или площадь.
- Форматирование: Представление данных в удобном для вывода формате без изменения исходных полей.
Пример:
from pydantic import BaseModel, computed_field
class Order(BaseModel):
price: float
quantity: int
@computed_field
@property
def total_cost(self) -> float:
"""Вычисляет общую стоимость заказа."""
return self.price * self.quantity
# Создаем экземпляр
order = Order(price=10.5, quantity=4)
# Вычисляемое поле доступно как обычный атрибут
print(order.total_cost) # Вывод: 42.0
# Поле включается в сериализованный объект
print(order.model_dump())
# Вывод: {'price': 10.5, 'quantity': 4, 'total_cost': 42.0}
Ключевые отличия от стандартного @property:
В отличие от обычного @property, @computed_field полностью интегрируется с экосистемой Pydantic:
- Сериализация: Поле автоматически включается в вывод
.model_dump()и.model_dump_json(). - JSON Schema: Поле попадает в генерируемую JSON Schema, что важно для интеграции с фреймворками вроде FastAPI для автоматической генерации документации.
Ответ 18+ 🔞
А, слушай, смотри, есть в Pydantic такая штука — декоратор @computed_field. Появился со второй версии, ну, чтобы не ебаться с костылями. Суть в чём: ты можешь сделать поле, которое нихуя не приходит извне, а вычисляется на лету из других полей твоей же модели. И главная фишка — оно потом спокойно попадает в JSON при дампе, в документацию API и вообще везде, где надо.
Где это, блядь, пригождается:
- Производные поля, ёпта. Ну, типа
full_nameизfirst_nameиlast_name. Банально, но нужно. - Агрегация какая-нибудь. Посчитать общую сумму заказа, площадь комнаты — всё такое.
- Форматирование для вывода. Чтобы не портить исходные данные, но на выходе дать красивую строку.
Смотри, как это выглядит вживую:
from pydantic import BaseModel, computed_field
class Order(BaseModel):
price: float
quantity: int
@computed_field
@property
def total_cost(self) -> float:
"""Вычисляет общую стоимость заказа."""
return self.price * self.quantity
# Создаем экземпляр
order = Order(price=10.5, quantity=4)
# Вычисляемое поле доступно как обычный атрибут
print(order.total_cost) # Вывод: 42.0
# Поле включается в сериализованный объект
print(order.model_dump())
# Вывод: {'price': 10.5, 'quantity': 4, 'total_cost': 42.0}
И вот, блядь, важный момент! Чем это лучше обычного @property?
Да тем, что это не просто геттер, который только в коде живёт. Это полноценное поле Pydantic, ёбта!
- Сериализация: Оно автоматом лезет в
.model_dump()и.model_dump_json(). Не надо руками его добавлять, ебать мои старые костыли. - JSON Schema: Оно попадает в схему, которую Pydantic генерирует. А это, например, для FastAPI — готовый кусок документации в Swagger. Красота, а не жизнь.
Короче, если раньше ты городил огород с кастомными валидаторами или методами, чтобы поле в вывод просочилось, то теперь — @computed_field и никаких геморроев. Всё чисто, по-взрослому.