You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为类方法返回值做类型提示以匹配初始化传入的函数

解决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)

错误原因分析

  1. 第一个错误:_single_shot_wrapper返回TypeVar _R,但方法参数中没有任何关联该TypeVar的输入,mypy要求返回TypeVar的函数必须有包含同TypeVar的参数来绑定类型。
  2. 第二个错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 22:47:01