如何让Pyright认可《流畅的Python》中的Python泛型Protocol示例?
解决Pyright对泛型Protocol检查的错误问题
你的代码能正常运行,但Pyright报错的核心原因是泛型Protocol的约束关联不明确,Pyright无法自动推断int、str、list这些内置类型符合Repeatable协议的要求。下面提供两种修改方案,均可通过Pyright检查:
方案1:明确泛型Protocol的约束绑定
修改double函数的类型变量约束,指定RT需要符合Repeatable[RT](即类型RT的实例调用__mul__后返回自身类型):
from typing import Protocol class Repeatable[T](Protocol): def __mul__(self: T, repeat_count: int) -> T: ... # 关键修改:将约束从Repeatable改为Repeatable[RT] def double[RT: Repeatable[RT]](x: RT) -> RT: return x * 2 if __name__ == '__main__': print(double(3)) print(double('A')) print(double([1, 2]))
方案2:使用Python 3.11+的Self类型简化定义
如果你的Python版本是3.11或以上,可通过typing.Self替代泛型参数,让协议定义更直观,Pyright能直接识别内置类型的匹配关系:
from typing import Protocol, Self class Repeatable(Protocol): # 用Self替代泛型T,明确返回自身类型 def __mul__(self, repeat_count: int) -> Self: ... def double[RT: Repeatable](x: RT) -> RT: return x * 2 if __name__ == '__main__': print(double(3)) print(double('A')) print(double([1, 2]))
原理说明
Pyright对静态类型检查的要求更严格,原代码仅用Repeatable作为约束时,泛型参数的关联逻辑不清晰。修改后,无论是显式绑定Repeatable[RT],还是用Self明确返回类型,都能让Pyright确认int、str、list的__mul__方法完全符合协议签名(接受int类型的重复次数,返回自身类型),从而通过检查。
内容的提问来源于stack exchange,提问作者Gorbatov Nikolay
相关产品推荐
相关产品推荐

