如何为被装饰的__getitem__和__setitem__正确添加类型提示?
解决Mypy签名不兼容问题
问题出在你的dict_operator装饰器没有保留原方法的精确类型签名,Mypy无法识别被装饰后的__getitem__和__setitem__与父类dict的签名匹配。
要修复这个问题,需要用ParamSpec和TypeVar让装饰器准确传递原方法的类型信息:
from typing import TypeVar, Callable, Type, ParamSpec, Any P = ParamSpec("P") R = TypeVar("R") T = TypeVar("T", bound="CustomDict") class CustomDict(dict): def __init__(self) -> None: super().__init__() class dict_operator: def __init__(self, method: Callable[P, R]) -> None: self.method = method def __get__(self, instance: T | None, owner: Type[T]) -> Callable[P, R]: def wrapper(*args: P.args, **kwargs: P.kwargs) -> R: results = self.method(instance, *args, **kwargs) print("Did something after __getitem__ or __setitem__") return results return wrapper @dict_operator def __getitem__(self, key: Any) -> Any: return super().__getitem__(key) @dict_operator def __setitem__(self, key: Any, value: Any) -> None: super().__setitem__(key, value)
关键修改点:
- 新增
ParamSpec("P")捕获原方法的参数类型,TypeVar("R")捕获返回值类型,让装饰器能精确传递签名。 - 把
dict_operator的__init__参数类型从Callable[..., Any]改为Callable[P, R],明确绑定原方法的参数和返回值。 __get__方法返回Callable[P, R],确保包装后的函数签名和原方法完全一致。- 调整
wrapper函数的参数为*args: P.args, **kwargs: P.kwargs,返回R,严格匹配原方法的调用方式。
这样修改后,Mypy就能识别被装饰后的方法签名和父类dict的签名兼容,不会再抛出类型错误。
内容的提问来源于stack exchange,提问作者Colin
相关产品推荐
相关产品推荐

