Python type hints. Как уточнить тип объекта?

from abc import ABCMeta, abstractmethod


class AbstractObject(metaclass=ABCMeta):
    pass


class BObject(AbstractObject):
    pass


class CObject(AbstractObject):
    pass


class A(metaclass=ABCMeta):
    def restore_object(self) -> "AbstractObject":
        a = self.create_object()
        # другие действия
        return a

    @abstractmethod
    def create_object(self) -> "AbstractObject":
        pass


class B(A):

    def create_object(self):
        return BObject()


class C(A):

    def create_object(self):
        return CObject()


b_manager = B()
c_manager = C()

one_object: "BObject" = b_manager.restore_object()  # здесь ошибка типа
two_object: "CObject" = c_manager.restore_object()  # Expected type 'BObject', got 'AbstractObject' instead

При вызове метода "restore_object" не получается указать нужный тип. В некоторых других языках можно уточнить возвращаемый тип, от абстрактного, примерно тем синтаксисом, который я указал. А как решить эту задачу в Питоне?


Ответы (2 шт):

Автор решения: MaxU

попробуйте так:

class AbstractObject(metaclass=ABCMeta):
    pass


class A(metaclass=ABCMeta):
    def restore_object(self) -> AbstractObject:
        a = self.create_object()
        # другие действия
        return a

или так, если ожидается неизвестный заранее тип:

from typing import Any

class A(metaclass=ABCMeta):
    def restore_object(self) -> Any:
        a = self.create_object()
        # другие действия
        return a
→ Ссылка
Автор решения: insolor

Можно сделать класс A дженериком (если вы используете Python 3.5 или новее):

from typing import TypeVar, Generic

...

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


class A(Generic[T]):
    def restore_object(self) -> T:
        a = self.create_object()
        # другие действия
        return a

    @abstractmethod
    def create_object(self) -> T:
        pass


class B(A[BObject]):

    def create_object(self):
        return BObject()


class C(A[CObject]):

    def create_object(self):
        return CObject()


b_manager = B()
c_manager = C()

one_object: "BObject" = b_manager.restore_object()
two_object: "CObject" = c_manager.restore_object()
→ Ссылка