如何解决Python中make_request函数的泛型返回值类型检查问题?
解决make_request泛型函数的mypy报错及泛型类调用问题
问题根源
make_request里定义了泛型TEntityDict但未在参数中引用,mypy会报「未使用的类型变量」错误- 之前用
type=TDoc伪参数的方式,在泛型类(比如User)中调用时,会触发「在非类型上下文使用类型变量」的错误
解决办法
1. 将TEntityDict设为函数级泛型参数
修改make_request的定义,让TEntityDict属于函数自身的泛型参数,无需将整个类泛型化。这样每次调用make_request都能独立指定返回类型:
from typing import TypeVar, Generic, TypedDict, NotRequired, Unpack, Callable import requests TParams = TypeVar("TParams", bound=dict[str, str]) TBody = TypeVar("TBody", bound=dict[str, str]) TEntityDict = TypeVar("TEntityDict") class SessionFunctionKwargs(Generic[TParams, TBody], TypedDict): params: NotRequired[TParams | None] data: NotRequired[TBody | str | None] timeout: float verify: bool class APICall: def make_request( self, fn: Callable[..., requests.models.Response], endpoint: str, **kwargs: Unpack[SessionFunctionKwargs[TParams, TBody]], ) -> TEntityDict: # 实际请求逻辑示例:调用传入的fn并解析响应 response = fn(endpoint, **kwargs) return response.json()
2. 泛型类中调用时显式指定泛型参数
在User类的retrieve方法里,调用make_request时通过[TDoc]显式指定泛型类型,规避非类型上下文的错误:
TDoc = TypeVar("TDoc") class User(Generic[TDoc]): def __init__(self, api_call: APICall, endpoint_path: str): self.api_call = api_call self._endpoint_path = endpoint_path def retrieve(self) -> TDoc: # 显式声明make_request的返回类型为TDoc return self.api_call.make_request[TDoc]( requests.get, self._endpoint_path, timeout=10.0, verify=True )
3. 备选方案:用cast做类型断言
如果不想修改make_request的定义,也可以在调用后用cast强制标注返回类型(需确保实际返回值符合目标类型,否则可能引发运行时问题):
from typing import cast class User(Generic[TDoc]): def retrieve(self) -> TDoc: raw_data = self.api_call.make_request( requests.get, self._endpoint_path, timeout=10.0, verify=True ) return cast(TDoc, raw_data)
方案说明
- 函数级泛型让
make_request灵活适配不同返回类型,避免将整个大型类泛型化带来的复杂度 - 显式指定泛型参数
[TDoc]是在类型上下文中操作,符合mypy的检查规则,不会触发错误 cast方案简洁直接,但属于手动类型断言,需要开发者自行保证类型匹配
内容的提问来源于stack exchange,提问作者StrakisOPou
相关产品推荐
相关产品推荐

