Base class 方法的类型提示基于 Subclass
Type hint of Base class method based on Subclass
创建基础 class 时,其请求方法对所有子class 完全相同。似乎没有一种简单的方法可以根据 subclass 发出请求来获得单独的类型提示。
下面的例子是我目前解决这个问题的方法,但似乎还有更好的方法。
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 上指定响应类型,或者只覆盖方法签名而不覆盖功能?
类似于(我知道这不起作用):
class FooRequest(Request):
@classmethod
def make_request(...) -> FooResponse: ...
我认为使用 Generic[T] 和 TypeVar() 之类的东西可能是一种可行的方法?
也许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)
现在您的 FooRequest
和 BarRequest
不再需要提供 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)
创建基础 class 时,其请求方法对所有子class 完全相同。似乎没有一种简单的方法可以根据 subclass 发出请求来获得单独的类型提示。
下面的例子是我目前解决这个问题的方法,但似乎还有更好的方法。
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 上指定响应类型,或者只覆盖方法签名而不覆盖功能?
类似于(我知道这不起作用):
class FooRequest(Request):
@classmethod
def make_request(...) -> FooResponse: ...
我认为使用 Generic[T] 和 TypeVar() 之类的东西可能是一种可行的方法?
也许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)
现在您的 FooRequest
和 BarRequest
不再需要提供 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)