保留functools.wraps时,如何为类实例方法装饰器添加正确类型注解?
问题:保留
functools.wraps时解决Pyright参数报错 以下是示例代码:
from typing import ParamSpec, TypeVar, Callable, Concatenate import functools P = ParamSpec("P") R = TypeVar("R") def deco(func: Callable[Concatenate[R, int, int, P], None]): @functools.wraps(func) def wrapper(self, *args: P.args, **kwargs: P.kwargs): return func(self, 1, 2, *args, **kwargs) return wrapper class A: @deco def main(self, a, b, c): pass a = A() a.main(3)
问题现象
最后一行代码a.main(3)中,Pyright给出报错信息:Argument missing for parameter "c"。移除@functools.wraps(func)后报错即可消失,但需在保留该装饰器的前提下解决问题,且代码结构不可更改。
解决方案
核心问题是装饰器的返回类型未明确标注,导致Pyright无法正确推断wrapper的参数签名。只需给deco函数添加返回类型注解-> Callable[P, None],明确告知类型检查器:装饰器返回的函数仅接受P所定义的参数,而非原函数的完整参数列表。
修改后的装饰器定义如下:
def deco(func: Callable[Concatenate[R, int, int, P], None]) -> Callable[P, None]: @functools.wraps(func) def wrapper(self, *args: P.args, **kwargs: P.kwargs): return func(self, 1, 2, *args, **kwargs) return wrapper
添加注解后,Pyright就能正确识别a.main(3)的参数合法性——装饰后的main函数仅需接收原函数中self、a、b之外的参数c(对应示例中的3)。
内容的提问来源于stack exchange,提问作者Junyang Feng
相关产品推荐
相关产品推荐

