@ilya_chch

Как аннотировать тип классового атрибута, который будет переопределен?

Допустим, есть абстрактный класс:

import abc
from pydantic import BaseModel

class Abstract(abc.ABC):
    context_class: ClassVar[Type['BaseModel']]
    error: ClassVar[Type[Exception]]

    def __init__(self, data: Dict) -> None:
        self.context = self.context_class(**data)

    @abc.abstractmethod
    def process(self) -> None:
        pass


И есть его наследник, в котором атрибут `context_class` переопределен наследником `BaseModel`:

class Context(BaseModel):
    email: str

class Concrete(Abstract):
    context_class = Context

    def process(self) -> None:
        print(self.context.email)


При запуске Mypy - падает ошибка:
... error: "BaseModel" has no attribute "email"

как правильно указать тип в абстрактном классе?

Уточнение:
Python 3.8.2
Mypy 0.770
Pydantic 1.6.1
  • Вопрос задан
  • 42 просмотра
Решения вопроса 1
@ilya_chch Автор вопроса
Решение нашлось:
import abc
from typing import ClassVar, Type, Dict, Generic, TypeVar
from pydantic import BaseModel

T = TypeVar('T', bound=BaseModel)


class Abstract(abc.ABC, Generic[T]):
    context_class: ClassVar[Type[T]]
    error: ClassVar[Type[Exception]]

    def __init__(self, data: Dict) -> None:
        self.context = self.context_class(**data)

    @abc.abstractmethod
    def process(self) -> None:
        pass


class Context(BaseModel):
    email: str


class Concrete(Abstract[Context]):
    context_class = Context

    def process(self) -> None:
        print(self.context.email)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы