Python 3.11多继承模型类型注解实现与mypy类型推断问题
解决共享元类关联类的Mypy类型推断问题
问题场景
我们有一组共享元类AMeta的关联类,核心结构包括:
- 抽象类
A,元类型为AMeta - 抽象类
ADerived,同时继承自A和另一个类C
在此基础上,会动态创建ADerived的实现类(比如D1、D2),以及A的实现类(比如E、F)。A的每个实现类都有一个类变量_DerivedModel,指向对应的ADerived子类,但目前Mypy无法正确推断该变量的具体类型。
简化后的示例代码如下:
from __future__ import annotations from typing import TypeVar, Type, ClassVar _BModel = TypeVar("_BModel", bound="ADerived") class C: pass class AMeta(type): @property def BModel(cls: Type[A]) -> Type[_BModel]: return cls._DerivedModel # Abstract Models class A(metaclass=AMeta): _DerivedModel: ClassVar[Type[_BModel]] class ADerived(A, C): pass # Derived Models (this models are dynamically created) class D1(ADerived): pass class D2(ADerived): pass # Implementations class E(A): _DerivedModel = D1 class F(A): _DerivedModel = D2 MyDerived1 = E.BModel # 期望Mypy推断为type[D1] MyDerived2 = F.BModel # 期望Mypy推断为type[D2]
解决方法
要让Mypy正确追踪_DerivedModel的具体类型,需要把A定义为泛型类,让每个A的子类绑定对应的ADerived子类。具体修改如下:
from __future__ import annotations from typing import TypeVar, Type, ClassVar, Generic # 定义绑定到ADerived的TypeVar _BModelT = TypeVar("_BModelT", bound="ADerived") class C: pass class AMeta(type): # 调整类型注解,适配泛型类的类型 @property def BModel(cls: Type[A[_BModelT]]) -> Type[_BModelT]: return cls._DerivedModel # 将A改为泛型类,继承Generic class A(Generic[_BModelT], metaclass=AMeta): # 类变量类型绑定到泛型参数 _DerivedModel: ClassVar[Type[_BModelT]] class ADerived(A[_BModelT], C): pass # 动态创建的实现类保持不变 class D1(ADerived): pass class D2(ADerived): pass # 实现类会自动推断泛型参数,也可以显式指定比如E(A[D1]) class E(A): _DerivedModel = D1 class F(A): _DerivedModel = D2 # 现在Mypy可以正确推断类型:MyDerived1是Type[D1],MyDerived2是Type[D2] MyDerived1 = E.BModel MyDerived2 = F.BModel
关键修改点
- 将
A改为泛型类,继承Generic[_BModelT],让每个子类都能关联具体的ADerived子类类型 - 元类
AMeta的BModel属性中,将cls的类型注解改为Type[A[_BModelT]],确保返回值和泛型参数一致 A中的_DerivedModel类变量类型绑定到泛型参数_BModelT,让Mypy能追踪每个子类的具体赋值
内容的提问来源于stack exchange,提问作者Bravhek
相关产品推荐
相关产品推荐

