使用mypy检查Python单例工厂类时的类型提示错误求助
单例实现的Mypy类型检查问题
我常使用如下代码结构生成单例:
class Thing: pass class ThingSingletonFactory: _thing = None def __new__(cls) -> Thing: if cls._thing is None: cls._thing = Thing() return cls._thing def get_thing() -> Thing: return ThingSingletonFactory() thing = get_thing() same_thing = get_thing() assert thing is same_thing
ThingSingletonFactory类存储Thing的唯一实例,每次调用ThingSingletonFactory()时返回该实例,适用于API客户端、logging.Logger等场景。为现有项目添加mypy类型检查时,出现如下错误:
line 8: error: Incompatible return type for "__new__" (returns "Thing", but must return a subtype of "ThingSingletonFactory") [misc] line 15: error: Incompatible return value type (got "ThingSingletonFactory", expected "Thing") [return-value]
我认为代码中的类型提示是正确的:__new__()和get_thing()确实返回Thing类型。请问如何修改类型提示让mypy通过?或是该实现方式本身不规范?
问题原因
Mypy严格遵循Python类型规则:__new__方法的返回值必须是当前类(或其子类)的实例,你的代码让它返回Thing类型,违反了类型约束;同时Mypy默认认为ThingSingletonFactory()返回的是工厂类实例,和get_thing声明的返回Thing类型冲突。
修复方案
方案1:规范实现(推荐)
不要让__new__返回非自身类的实例,改用类方法提供单例,既符合Python类设计规范,又能直接通过Mypy检查:
class Thing: pass class ThingSingletonFactory: _thing: Thing | None = None @classmethod def get_instance(cls) -> Thing: if cls._thing is None: cls._thing = Thing() return cls._thing def get_thing() -> Thing: return ThingSingletonFactory.get_instance() thing = get_thing() same_thing = get_thing() assert thing is same_thing
方案2:适配现有代码(临时过渡)
如果不想改动现有结构,可以通过类型强制转换或忽略检查来绕过错误,但不推荐长期使用:
方式A:用cast强制转换类型
from typing import cast class Thing: pass class ThingSingletonFactory: _thing: Thing | None = None def __new__(cls) -> Thing: if cls._thing is None: cls._thing = Thing() return cast(Thing, cls._thing) def get_thing() -> Thing: return cast(Thing, ThingSingletonFactory())
方式B:添加# type: ignore跳过检查
class Thing: pass class ThingSingletonFactory: _thing = None def __new__(cls) -> Thing: if cls._thing is None: cls._thing = Thing() return cls._thing # type: ignore[misc] def get_thing() -> Thing: return ThingSingletonFactory() # type: ignore[return-value]
总结
你的原实现属于非常规用法,__new__的语义是创建并返回当前类的实例,返回其他类型实例不符合Python设计规范,因此Mypy报错。优先选择方案1的类方法实现,兼顾规范与类型检查要求。
内容的提问来源于stack exchange,提问作者Danielle M.
相关产品推荐
相关产品推荐

