为何mypy抛出‘无法实例化抽象类’错误?
问题原因
mypy对类型联合的处理存在阈值限制:当你在FEATURE_CLASSES中放入3个及以上Feature的子类时,mypy会自动将列表的类型推断为List[Type[Feature]](抽象类的类型),而非多个具体子类的联合类型。此时mypy无法识别你实际实例化的是具体子类,因此抛出“无法实例化抽象类”的错误。而当列表中只有2个子类时,mypy会保留联合类型(如Type[Count] | Type[RecencyDays]),能正确识别实例化操作的合法性。
解决方法
方法1:显式标注联合类型
直接给FEATURE_CLASSES指定具体子类的联合类型,让mypy明确每个元素都是可实例化的具体类:
from typing import ClassVar, Tuple, Type class PurchasingFeatureGenerator: FEATURE_CLASSES: ClassVar[Tuple[Type[Count], Type[GrossSpend], Type[RecencyDays]]] = ( Count, GrossSpend, RecencyDays )
方法2:使用绑定子类的TypeVar
定义一个绑定到Feature的TypeVar,用它来约束FEATURE_CLASSES的类型,既保证类型安全又避免重复写多个子类:
from typing import TypeVar, ClassVar, Tuple, Type # 定义绑定到Feature的TypeVar,只接受Feature的非抽象子类 FeatureSubclass = TypeVar('FeatureSubclass', bound='Feature') class PurchasingFeatureGenerator: FEATURE_CLASSES: ClassVar[Tuple[Type[FeatureSubclass], ...]] = ( Count, GrossSpend, RecencyDays )
方法3:添加类型断言(临时方案)
在实例化代码前添加断言或过滤条件,告诉mypy当前类是可实例化的非抽象类:
import inspect [ f[0](as_at=self.as_at, feature_period=f[1]) for f in ( (cls, fp) for cls in self.FEATURE_CLASSES for fp in self.feature_periods if not inspect.isabstract(cls) # 过滤抽象类 ) ]
注意:方法3属于临时 workaround,更推荐前两种显式类型标注的方案,能从根源解决类型推断问题。
内容的提问来源于stack exchange,提问作者jamiet
相关产品推荐
相关产品推荐

