You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 12:28:05