Я работаю с моделями 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
...
Моя проблема здесь в том, что из-за функции проверки я не знаю, где я мог бы написать строку документации, чтобы описать два разных поведения.
Я думаю, что это не проблема. Поведение 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 выдаст значимую ошибку.
Надеюсь, это поможет!