如何为类方法返回值做类型提示以匹配初始化传入的函数
解决Qt PySide2单次触发Slot的mypy类型提示问题
背景
基于Qt PySide2的信号槽机制,实现了SingleShotConnect类,确保Slot仅在Signal第一次触发时执行,随后自动断开关联。但代码触发两个mypy类型错误:
问题代码
import typing as _t from Qt import QtCore as _QtCore _R = _t.TypeVar("_R") class SingleShotConnect: _INSTANCES: _t.ClassVar[_t.Set["SingleShotConnect"]] = set() def __init__( self, signal: "_QtCore.SignalInstance", slot: _t.Callable[..., _R], ) -> None: self._signal = signal self._slot = slot self._signal.connect(self._single_shot_wrapper) SingleShotConnect._INSTANCES.add(self) # error: A function returning TypeVar should receive at least one argument containing the same TypeVar [type-var] def _single_shot_wrapper(self, *args, **kwargs) -> _R: self._signal.disconnect(self._single_shot_wrapper) SingleShotConnect._INSTANCES.remove(self) # error: Incompatible return value type (got "_R@__init__", expected "_R@_single_shot_wrapper") return self._slot(*args, **kwargs)
错误原因分析
- 第一个错误:
_single_shot_wrapper返回TypeVar_R,但方法参数中没有任何关联该TypeVar的输入,mypy要求返回TypeVar的函数必须有包含同TypeVar的参数来绑定类型。 - 第二个错误:mypy将
__init__中的_R和_single_shot_wrapper中的_R视为两个独立的类型绑定,无法识别二者指向同一返回类型。
解决方案(不依赖ParamSpec)
将类改造为泛型类,让_R成为类级别的泛型参数,绑定到实例的类型信息,同时显式标注_slot的类型:
import typing as _t from Qt import QtCore as _QtCore _R = _t.TypeVar("_R") class SingleShotConnect(_t.Generic[_R]): _INSTANCES: _t.ClassVar[_t.Set["SingleShotConnect[_t.Any]"]] = set() def __init__( self, signal: "_QtCore.SignalInstance", slot: _t.Callable[..., _R], ) -> None: self._signal = signal # 显式标注_slot的类型,确保和类泛型_R绑定 self._slot: _t.Callable[..., _R] = slot self._signal.connect(self._single_shot_wrapper) SingleShotConnect._INSTANCES.add(self) def _single_shot_wrapper(self, *args: _t.Any, **kwargs: _t.Any) -> _R: self._signal.disconnect(self._single_shot_wrapper) SingleShotConnect._INSTANCES.remove(self) # 此时self._slot的返回类型与方法返回的_R完全一致,mypy可正确识别 return self._slot(*args, **kwargs)
补充说明
如果泛型类改造后仍有类型提示问题,可通过_t.cast强制标注返回类型,明确告知mypy类型匹配:
return _t.cast(_R, self._slot(*args, **kwargs))
原理说明
- 泛型类让
_R与实例绑定,而非模块或方法级别的独立TypeVar,解决了mypy对TypeVar绑定的要求。 - 显式标注
_slot的类型,确保其返回类型与类的泛型参数_R一致,消除了返回类型不匹配的错误。
内容的提问来源于stack exchange,提问作者Parikshit
相关产品推荐
相关产品推荐

