← Назад к вопросам

Какая область применения Decorator computed field в pydantic?

1.8 Middle🔥 121 комментариев
#FastAPI и Flask#REST API и HTTP

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Применение Decorator computed_field в Pydantic

Decorator @computed_field в Pydantic v2 — это инструмент для определения вычисляемых полей, которые динамически рассчитываются на основе других полей модели. Это мощный механизм для добавления логики вычисления данных без сохранения их в базу данных.

Основные области применения

1. Вычисляемые производные значения

Основная цель — получить значение, которое логически вытекает из других полей модели:

from pydantic import BaseModel, computed_field

class Order(BaseModel):
    price: float
    quantity: int
    tax_rate: float = 0.1
    
    @computed_field
    @property
    def total_price(self) -> float:
        """Цена с учётом налога"""
        return self.price * self.quantity * (1 + self.tax_rate)
    
    @computed_field
    @property
    def subtotal(self) -> float:
        """Сумма без налога"""
        return self.price * self.quantity

2. Трансформация для API ответов

Частый случай — когда нужно преобразовать внутреннее представление в формат, понятный клиенту:

from datetime import datetime
from pydantic import BaseModel, computed_field

class User(BaseModel):
    first_name: str
    last_name: str
    created_at: datetime
    
    @computed_field
    @property
    def full_name(self) -> str:
        """Полное имя пользователя"""
        return f"{self.first_name} {self.last_name}"
    
    @computed_field
    @property
    def days_since_creation(self) -> int:
        """Дней с момента создания"""
        return (datetime.now() - self.created_at).days

3. Условная логика при сериализации

Вычисляемые поля позволяют добавлять условную бизнес-логику, которая применяется только при преобразовании в JSON:

from pydantic import BaseModel, computed_field

class Product(BaseModel):
    name: str
    price: float
    discount: float = 0.0
    
    @computed_field
    @property
    def display_price(self) -> str:
        """Цена в формате для отображения"""
        if self.discount > 0:
            return f"${self.price * (1 - self.discount):.2f} (скидка {self.discount*100:.0f}%)"
        return f"${self.price:.2f}"

4. Агрегирование данных из связанных объектов

Особенно полезно при работе с вложенными моделями:

from pydantic import BaseModel, computed_field
from typing import List

class Comment(BaseModel):
    text: str
    rating: int

class BlogPost(BaseModel):
    title: str
    comments: List[Comment]
    
    @computed_field
    @property
    def average_rating(self) -> float:
        """Средняя оценка из всех комментариев"""
        if not self.comments:
            return 0.0
        return sum(c.rating for c in self.comments) / len(self.comments)
    
    @computed_field
    @property
    def comment_count(self) -> int:
        """Количество комментариев"""
        return len(self.comments)

5. Кэширование вычислений

Чтобы избежать пересчёта для дорогостоящих операций, можно использовать cached_property:

from functools import cached_property
from pydantic import BaseModel, computed_field

class DataAnalysis(BaseModel):
    data: List[float]
    
    @computed_field
    @property
    def statistics(self) -> dict:
        """Статистика по данным (вычисляется один раз)"""
        return {
            "mean": sum(self.data) / len(self.data),
            "min": min(self.data),
            "max": max(self.data)
        }

Ключевые различия от обычных полей

  • Не требуют инициализации — вычисляются автоматически при доступе
  • Включаются в model_dump() — по умолчанию присутствуют в JSON
  • Только для чтения — нельзя установить напрямую
  • Выполняются при сериализации — может быть затратно для больших объёмов данных

Выводы

Деcorator @computed_field идеален для случаев, когда нужна динамическая обработка данных при сериализации, без усложнения логики модели. Это делает код более чистым и поддерживаемым, отделяя бизнес-логику от структуры данных.