传递泛型类作为值时类型提示异常,是代码问题还是pyright Bug?
Pyright泛型类条件选择后的类型提示问题
当使用条件表达式(a = cls1 if cond else cls2)或字典映射选择泛型类时,pyright无法正确推断实例化后方法的TypeVar类型,导致参数提示为Any,但mypy能正确检查类型错误。示例代码如下:
from typing import Generic, TypeVar T = TypeVar("T") class Foo(Generic[T]): def __init__(self, t: T): self.t = t def print(self, t: T): print(t, self.t) class Foo2(Foo[T]): def print(self, t: T): if t == self.t: print("equal") else: Foo.print(self, t) check_equal: bool printer = Foo2 if check_equal else Foo a = printer(3) a.print(...) # pyright提示参数为Any,mypy能检查非int类型错误
问题分析
你的代码本身没有错误,这是pyright在处理泛型类的联合类型赋值时的类型推断限制:
- pyright会将
printer推断为Type[Foo[T]] | Type[Foo2[T]],但在实例化printer(3)后,未能将T的具体类型(int)绑定到实例的方法参数上,导致提示为Any。 - mypy的泛型推断逻辑更完善,能够追踪到实例化时传入的
int类型,进而正确校验print方法的参数类型。
解决方案
1. 显式标注printer的类型
通过明确指定泛型类型,帮助pyright绑定TypeVar:
from typing import Type, Union # 方式1:用Union标注具体的类类型 printer: Union[Type[Foo[T]], Type[Foo2[T]]] = Foo2 if check_equal else Foo # 方式2:利用子类兼容性,直接标注为父类的泛型类型 printer: Type[Foo[T]] = Foo2 if check_equal else Foo
2. 实例化时显式指定泛型参数
直接给类指定泛型类型,强制pyright识别参数类型:
a = printer[int](3) a.print(...) # 此时会正确提示参数为int
内容的提问来源于stack exchange,提问作者LibrarristShalinward
相关产品推荐
相关产品推荐

