MyPy严格校验带参数装饰器时出现多类报错该如何解决?
问题修复方案
你的代码核心问题是带参数装饰器的外层函数返回值类型标注错误,同时存在多余的类型强转逻辑,导致mypy无法正确识别装饰器的类型。以下是可在严格模式下完全通过mypy检查的修正代码:
from time import sleep from typing import TypeVar, Any, Callable, cast F = TypeVar('F', bound=Callable[..., Any]) # 修正外层函数返回值类型:接收两个int参数,返回一个接受F、返回F的装饰器 def multi_try_if_error(n_tries: int, sleep_duration: int) -> Callable[[F], F]: def decorator(fn: F) -> F: # 补全wrapper的参数和返回值标注 def wrapper(*args: Any, **kwargs: Any) -> Any: caught: Exception for _ in range(n_tries): try: return fn(*args, **kwargs) except Exception as e: caught = e sleep(sleep_duration) raise ValueError(caught) return cast(F, wrapper) # 删掉外层多余的cast,返回值已经符合类型标注 return decorator @multi_try_if_error(n_tries=3, sleep_duration=1) def query_db(q: str) -> None: return
具体修改点
- 调整
multi_try_if_error的返回值类型:原标注F是错误的,外层函数并不是返回和原函数同类型的可调用对象,而是返回一个「接收原函数类型、返回原函数类型」的装饰器函数,因此标注改为Callable[[F], F] - 补全
wrapper函数的参数、返回值类型标注,解决函数未标注的报错 - 给
caught变量补全类型标注,避免strict模式下未初始化变量的类型报错 - 删除外层多余的
cast(F, decorator)强转逻辑,此时返回的decorator已经完全匹配标注的返回值类型,无需强转
修改后装饰器会完整保留原函数的类型签名,后续调用被装饰函数时的参数、返回值类型校验均会正常生效。
内容的提问来源于stack exchange,提问作者Zach
相关产品推荐
相关产品推荐

