Можно ли описать поле модели Pydantic как определенный тип, допуская при этом инициализацию несколькими?

Я работаю с моделями Pydantic для реализации класса данных и хочу, чтобы определенное поле было неизменяемым, поэтому я использую кортежи. Однако для удобства я хочу иметь возможность передавать на вход как список, так и кортеж.

Я рассматриваю двух разных пользователей класса данных:

  • автор: хочет передать как изменяемые, так и неизменяемые типы для инициализации объекта.
  • читатель: хочет знать, что поле, которое его интересует, является неизменным при чтении объекта.

Можно ли описать поле объекта как кортеж, а объект __init__() как принимающий два типа?

На данный момент это реализовано следующим образом:

from pydantic import Field
from pydantic.dataclasses import dataclass
from typing import List, Union, Tuple

@dataclass(frozen=True)
class MyClass:
  """
  Description of MyClass

  Parameter
  ---------
  field: Union[List[int], Tuple[int, ...]]
  """

  @field_validator("field")
    def make_immutable(cls, field):
        if isinstance(field, list):
            return tuple(field)
        return field
...

Моя проблема здесь в том, что из-за функции проверки я не знаю, где я мог бы написать строку документации, чтобы описать два разных поведения.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
103
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я думаю, что это не проблема. Поведение Pydantic по умолчанию — приведение типов. Таким образом, заданный тип при инициализации будет принудительно преобразован (преобразован) в аннотированный тип. Если приведение пройдет успешно, все в порядке, и ваши данные будут сохранены как аннотированный тип. В случае неудачи будет выдана значимая ошибка. Это означает поле, которое помечено как Tuple[int, ...]:

from pydantic import Field
from pydantic.dataclasses import dataclass
from typing import Tuple

@dataclass(frozen=True)
class MyClass:
    """
    Description of MyClass

    Attributes
    ----------
    field: Tuple[int, ...]
        Tuple of integer values.
    """
    field: Tuple[int, ...] = Field(...)

В любом случае можно создать экземпляр со списком или всем, что принимается tuple(). См. следующие примеры:

import numpy as np
print(MyClass(field=np.array([1, 2, 3])))
print(MyClass(field=[1, 2, 3]))
print(MyClass(field = {1, 2, 3}))

Что все печатают: MyClass(field=(1, 2, 3))

Я бы рекомендовал просто сохранить соглашение Pydantic. Нет необходимости в дополнительном валидаторе. Пользователи смогут создать экземпляр модели, используя все, что работает. Если это не сработает, Pydantic выдаст значимую ошибку.

Надеюсь, это поможет!

Другие вопросы по теме