如何消除mypy对泛型继承检测的报错?
解决泛型实例类型映射的mypy报错问题
代码修正方案
要让mypy认可你的代码,需要用Protocol描述泛型实例特有的属性(__orig_bases__和__orig_class__),同时替换无效的isinstance(obj, Generic)检查:
from typing import Generic, TypeVar, get_args, Protocol, runtime_checkable T = TypeVar("T") class Derived(Generic[T]): def method(self, val: T) -> T: return val d = Derived[int]() # 定义运行时可检查的Protocol,描述泛型实例的属性 @runtime_checkable class GenericInstance(Protocol): __orig_bases__: tuple __orig_class__: type def get_generic_types_mapping(obj: object) -> dict[type, type]: if isinstance(obj, GenericInstance): # 提取带类型参数的泛型基类 generic_base = next( origin for origin in obj.__orig_bases__ if hasattr(origin, "__origin__") and origin.__origin__ is Generic ) # 映射TypeVar到实际类型 return dict(zip(get_args(generic_base), get_args(obj.__orig_class__))) else: return {} assert get_generic_types_mapping(d) == {T: int} assert get_generic_types_mapping(object()) == {}
关键概念解释
为什么
isinstance(obj, Generic)无效?
Generic是typing模块中的特殊构造,仅用于标记类为泛型,本身不是可实例化的普通类,因此不能作为isinstance的第二个参数做类型检查。__orig_bases__和__orig_class__的来源
这两个属性是Python typing模块在处理泛型类实例化(比如Derived[int]())时自动添加的实现细节:
__orig_class__:指向实例化时的具体泛型类(比如Derived[int]),包含已绑定的类型参数。__orig_bases__:存储类的原始基类元组,其中包含带类型参数的Generic基类(比如Generic[int])。
它们不属于Python官方公开API,但运行时可以稳定访问。
- 处理未指定类型参数的泛型实例
如果希望对Derived()这种未绑定类型参数的实例抛出错误,可在函数中添加额外检查:
def get_generic_types_mapping(obj: object) -> dict[type, type]: if isinstance(obj, GenericInstance): # 现有逻辑... elif issubclass(type(obj), Generic): raise ValueError("该泛型实例未指定类型参数") else: return {}
内容的提问来源于stack exchange,提问作者2e0byo
相关产品推荐
相关产品推荐

