#python-3.x #python-typing #pydantic
Вопрос:
Давайте начнем с примера (простого и академичного).:
from typing import ClassVar, TypeVar, Generic, Any, Type
class Options:
pass
class Foo:
Opts: ClassVar[Options]
FooType = TypeVar('FooType', bound=Foo)
class GenericModel(Generic[FooType]):
opts: FooType.Opts # <-- not working
def configure(self, foo: Type[FooType]):
self.opts = foo.Opts
def another_use_case(self, opts: FooType.Opts): # <-- not working
# an argument is something from FooType
pass
# usage
class FooBar(Foo):
class Opts(Options):
optA: Any
wrap = Wrapper[FooBar]()
wrap.configure(FooBar)
Можно ли аннотировать тип opts
?
Python жалуется, что TypeVar
у него нет атрибута Opts
. Я обнаружил, что при TypeVar
ограничении привязка сохраняется, __bound__
но похоже, что getattr
класс не перегружен TypeVar
для доступа к атрибутам из связанного типа.
Я где-то ошибся или такие случаи вообще не поддерживаются набором текста на Python? Есть ли какое-либо обходное решение для этого? Я могу представить себе больше случаев, когда доступ к TypeVar
типам атрибутов ограниченного типа может быть полезен при типизации общих классов.
Реальный вариант использования для этого гораздо сложнее и зависит от Pydantic
. GenericModel
это Pydantic
модель, которую я пытаюсь сделать универсальной , поскольку у меня есть набор очень похожих моделей, которые отличаются в основном по типам, поэтому вместо того, чтобы иметь FooModel
BarModel
и так далее, Я хочу создать один GenericModel
класс и конкретизировать их, написав foo_model = GenericModel[Foo]()
, bar_model = GenericModel[Bar]()
. Для Pydantic
opts
автоматической проверки он должен быть правильно набран с аннотациями. Также с таким типом намеков, кто-то другой точно знает, что opts
должно быть.
Единственный обходной путь, который я нашел, — это ввести opts
as Any
и выполнить проверку в пользовательском валидаторе, однако это своего рода волшебство и делает код очень подверженным ошибкам, поскольку неясно, что opts
на самом деле это не так Any
. Следующий недостаток заключается в том, что эта модель используется в качестве полезной нагрузки, FastAPI
поэтому я потерял всю схему типов в сгенерированной OpenAPI
спецификации.