python 类中的方法可以用子类定义的类型进行注释吗?

问题描述

我有一个超类,它有一个由其子类共享的方法。但是,此方法应返回一个对象,其类型在子类上定义。我希望方法的返回类型是静态注释的(不是动态类型),以便使用子类的代码可以受益于 mypy 对返回值的类型检查。但是我不想为了提供它的类型注释而重新定义子类上的通用方法。使用 python 类型注释和 mypy 可以实现吗?

像这样:

from typing import Type

class AbstractModel:
    pass

class OrderModel(AbstractModel):
    def do_order_stuff():
        pass

class AbstractRepository:
    model: Type[AbstractModel]

    def get(self) -> model:
        return self.model()

class OrderRepository(AbstractRepository):
    model = OrderModel


repo = OrderRepository()
order = repo.get()

# Type checkers (like mypy) should recognize that this is valid
order.do_order_stuff()

# Type checkers should complain about this; because `OrderModel`
# does not define `foo`
order.foo()

这里的棘手之处在于 get() 是在超类 AbstractRepository 上定义的,它还不知道 model 的类型。 (并且 -> model 注释失败,因为尚未指定 model 的值)。

model 的值由子类指定,但子类没有(重新)定义 get() 以提供注释。看起来这应该是静态可分析的;虽然这有点棘手,因为它需要静态分析器跟踪从超类到子类的 model 引用。

有什么方法可以同时实现共享超类实现和精确的子类返回类型?

解决方法

AbstractRepository 定义为泛型类。

from typing import TypeVar,Generic,Type,ClassVar


T = TypeVar('T')

class AbstractRespotitory(Generic[T]):
    model: ClassVar[Type[T]]

    @classmethod
    def get(cls) -> T:
        return cls.model()

get 仅使用类属性,因此可以——而且可以说应该——是类方法。)