繁体   English   中英

基于子类的 Base class 方法的类型提示

[英]Type hint of Base class method based on Subclass

使用对所有子类完全相同的请求方法创建基础 class 时。 似乎没有一种简单的方法可以根据发出请求的子类来获得单独的类型提示。

下面的示例是我目前解决此问题的方法,但似乎有更好的方法。

class Response(TypeDict): ...

class FooResponse(Response): ...

class BarResponse(Response): ...

class Request:

    @classmethod
    def make_request(cls, args: Any) -> Response:
        # This will return a dict response based on cls.TYPE (if cls.TYPE == Foo, FooResponse will be returned)
        return execute_db_query(cls, args)


class FooRequest(Request):

    @classmethod
    def make_request(cls, args: Any) -> FooResponse:
        return FooResponse(**super().make_request(cls, args))


class BarRequest(Request):

    @classmethod
    def make_request(cls, args: Any) -> BarResponse:
        return BarResponse(**super().make_request(cls, args))

有没有更好的方法来做到这一点,或者通过在子类上指定响应类型,或者只是覆盖方法签名而不是功能?

类似的东西(我知道这不起作用):

class FooRequest(Request):
    @classmethod
    def make_request(...) -> FooResponse: ...

我会假设使用像 Generic[T] 和 TypeVar() 这样的东西可能是 go 的一种方式?

也许typing.overload是您所寻求的。

from __future__ import annotations
from typing import overload

class Request:
    @overload
    @classmethod
    def make_request(cls: FooRequest, args: Any) -> FooResponse: ...
    @overload
    @classmethod
    def make_request(cls: BarRequest, args: Any) -> BarResponse: ...
    
    def make_request(cls, args):
        return actual_implementation(cls, args)

现在您的FooRequestBarRequest不再需要提供make_request的实现(或类型提示)。


另一方面,如果您的唯一目标是输入提示 IDE,您可以:

from __future__ import annotations
from typing import TypeVar


class Response: ...
class FooResponse(Response): ...
class BarResponse(Response): ...

T = TypeVar('T', bound=Response, covariant=True)

class Request:
    @classmethod
    def make_request(cls: Request, args: Any) -> T: 
          return actual_implementation(cls, args


class FooRequest(Request):
    @classmethod
    def make_request(cls: FooRequest, args: Any) -> FooResponse:
          return super(FooRequest, cls).make_request(args)

这将使 IDE 接受

fooresponse: FooResponse = FooRequest.make_request(None)

但拒绝

fooresponse: FooResponse = Request.make_request(None)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM