Python 3.11中用Protocol+ParamSpec替代Callable时mypy报错问题排查
为什么mypy对带ParamSpec的Protocol函数类型报错,而Pylance不报错?
这不是你对Protocol的用法错误,而是mypy在处理结合ParamSpec的Protocol函数类型时的现有限制。
问题根源
你定义的FuncType Protocol要求函数接收固定的int和str参数,再加上P对应的可变参数部分。但mypy目前无法自动从传入的my_f(签名为(int, str, float) -> str)中推断出P应该匹配[float],因此会将P推断为<nothing>,直接导致类型不匹配的报错。
而Callable[Concatenate[int, str, P], R]是mypy原生支持的参数拼接语法,它能正确识别my_f的剩余参数对应P的部分,所以不会触发错误。Pylance对Protocol的类型推断逻辑更灵活,能正确解析这种场景,因此没有报错。
可行的解决办法
如果要让mypy通过检查,可以显式指定P和R的类型:
forwarder1[float, str](my_f, 1.2)
如果不需要自定义Protocol的额外逻辑,直接使用Callable结合Concatenate的写法会更省心,就像你写的forwarder2那样。
额外说明
这个问题属于mypy对ParamSpec与Protocol结合场景的支持不完善,并非你的代码写法有误。后续mypy版本可能会优化这部分的类型推断能力。
内容的提问来源于stack exchange,提问作者Kiuhnm
相关产品推荐
相关产品推荐

