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

可继承单例:如何通过元类确保__init__仅执行一次?

单例元类中避免父类__init__重复执行的解决方案

需求背景

  • 实现SingletonMeta元类,让任意类及所有派生类都成为单例
  • 父类(如A)的__init__中需分配依赖运行时参数的资源,且该资源整个程序生命周期仅分配一次,不受子类实例化时的super()调用影响

现有问题

现有单例元类实现能保证类及派生类的单例特性,但子类实例化时,通过super()调用父类__init__会导致父类的资源分配逻辑重复执行。

现有代码:

class SingletonMeta(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            instance = super().__call__(*args, **kwargs)
            cls._instances[cls] = instance
        return cls._instances[cls]

class A(metaclass=SingletonMeta):
    def __init__(self, resource_name):
        print(resource_name)

class B(A):
    def __init__(self, resource_name):
        super().__init__(resource_name)
        print(resource_name)

def main():
    a = A("A")
    b = B("B")

if __name__ == "__main__":
    main()

输出为:

A
A
B

不符合预期,需要输出:

A
B

解决方案

通过修改SingletonMeta元类,在类初始化阶段包装其__init__方法,添加类级别的初始化状态检查,确保每个类的__init__仅执行一次。

修改后的元类代码:

class SingletonMeta(type):
    _instances = {}
    # 记录已完成初始化的类
    _initialized_classes = set()

    def __init__(cls, name, bases, attrs):
        super().__init__(name, bases, attrs)
        # 包装原__init__方法,添加执行控制逻辑
        original_init = cls.__init__

        def wrapped_init(self, *args, **kwargs):
            if cls not in SingletonMeta._initialized_classes:
                original_init(self, *args, **kwargs)
                SingletonMeta._initialized_classes.add(cls)
        
        cls.__init__ = wrapped_init

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            instance = super().__call__(*args, **kwargs)
            cls._instances[cls] = instance
        return cls._instances[cls]

效果验证

使用原有的A、B类及测试代码运行,输出结果为:

A
B

完全符合需求,且无需修改A、B的任何代码。


内容的提问来源于stack exchange,提问作者Gulzar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:50:30