簡體   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