Pyre检测在带ABC类型提示的工厂模式中报`Invalid class instantiation`错误的解决方法
Pyre检测在带ABC类型提示的工厂模式中报
Invalid class instantiation错误的解决方法 我完全理解你的困扰——你想用ABC来强制子类遵循统一的初始化参数规范,同时用工厂模式封装类的创建逻辑,结果Pyre却误判你要实例化抽象类MyClassABC,抛出了Invalid class instantiation错误,而且你还不想丢掉ABC里抽象__init__带来的IDE参数提示,对吧?
问题原因分析
Pyre看到你的工厂方法返回类型是type[MyClassABC]时,会认为这个返回值可能包含抽象类本身(毕竟type[MyClassABC]涵盖了抽象类和它的所有子类)。当你调用factory_cls(name="test")时,它就会担心你在实例化一个带有抽象方法的类,从而抛出错误。
解决方法
方法一:用Callable替代type[]作为返回类型
我们可以把工厂方法的返回类型从type[MyClassABC]改成Callable[[str], MyClassABC],这样Pyre就会明白:返回的是一个可以接受str类型参数并生成MyClassABC实例的可调用对象(也就是子类的构造器),而不是抽象类本身。
修改后的完整代码:
from abc import abstractmethod from typing import Callable class MyClassABC: @abstractmethod def __init__(self, name: str) -> None: pass class MyClass2(MyClassABC): def __init__(self, name: str) -> None: self.name = name class MyClass(MyClassABC): def __init__(self, name: str) -> None: self.name = name class ClassFactory: MAPPING: dict[str, type[MyClassABC]] = { "myclass": MyClass, "myclass2": MyClass2, } @staticmethod def get_class() -> Callable[[str], MyClassABC]: return ClassFactory.MAPPING["myclass"] if __name__ == "__main__": factory_cls = ClassFactory.get_class() instance = factory_cls(name="test")
这个改动既保留了IDE对name: str参数的提示,又让Pyre不再误报错误,因为它明确知道返回的是可实例化的构造器。
方法二:用TypeVar约束子类类型
如果你更倾向于保留type[]的类型提示风格,可以通过TypeVar来明确表示返回的是MyClassABC的非抽象子类类型:
from abc import abstractmethod from typing import TypeVar, Type # 定义TypeVar,绑定到MyClassABC,代表它的所有具体子类 MyClassSubtype = TypeVar('MyClassSubtype', bound='MyClassABC') class MyClassABC: @abstractmethod def __init__(self, name: str) -> None: pass class MyClass2(MyClassABC): def __init__(self, name: str) -> None: self.name = name class MyClass(MyClassABC): def __init__(self, name: str) -> None: self.name = name class ClassFactory: MAPPING: dict[str, Type[MyClassSubtype]] = { "myclass": MyClass, "myclass2": MyClass2, } @staticmethod def get_class() -> Type[MyClassSubtype]: return ClassFactory.MAPPING["myclass"] if __name__ == "__main__": factory_cls = ClassFactory.get_class() instance = factory_cls(name="test")
这里的TypeVar告诉Pyre,返回的类型是MyClassABC的具体子类,而非抽象类本身,从而消除误报。
备注:内容来源于stack exchange,提问作者Rien
相关产品推荐
相关产品推荐

