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

使用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.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 20:50:11