我想为一组共享公共元类(
AMeta
)的相关类实现类型化,有两个“事实上的”抽象父类:
A
(:类型[AMeta])ADerived
- 也继承自另一个类C
。最后还有
ADerived
(D1
,D2
,...这些是动态创建的)和A
(E
,F
,...)父类的实际实现模型。
A
(E
,F
)的实现还有一个类型为ADerived
(_DerivedModel
)的类变量,我遇到的问题是试图让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 # Should be infered by mypy as type[D1]
MyDerived2 = F.BModel # Should be infered by mypy as type[D2]
为了帮助 mypy 在动态创建派生模型的复杂场景中正确推断类型,您可以在元类中使用
Type
函数以及 TypeVar
。以下修改后的代码应该有助于 mypy 正确推断类型:
from __future__ import annotations
from typing import TypeVar, Type, ClassVar, TypeVar, cast
_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 (these models are dynamically created)
class D1(ADerived):
pass
class D2(ADerived):
pass
# Implementations
class E(A):
_DerivedModel = D1
class F(A):
_DerivedModel = D2
# TypeVar for the dynamically created models
_MyDerived = TypeVar("_MyDerived", D1, D2)
MyDerived1: Type[_MyDerived] = cast(Type[_MyDerived], E.BModel)
MyDerived2: Type[_MyDerived] = cast(Type[_MyDerived], F.BModel)
# Now mypy should correctly infer MyDerived1 as D1 and MyDerived2 as D2.
这使用
TypeVar
_MyDerived
指定动态创建的模型允许的类型。然后使用 cast
函数指导 mypy 推断正确的类型。这应该有助于 mypy 正确地将 MyDerived1
推断为 D1
并将 MyDerived2
推断为 D2
。