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

能否部分实现Singleton模式?按参数返回相同/不同实例的方案探讨

实现同参数返回单实例的方案

你要的是基于参数的实例缓存——相同参数调用类时返回同一个实例,不同参数返回不同实例。不用搞两个类,有更简洁的实现方式:

方案一:重写类的__new__方法(推荐)

直接在目标类内部通过重写创建实例的__new__方法实现缓存,调用方式和你示例里完全一致:

class SomeClass:
    # 用类变量存储缓存的实例
    _instance_cache = {}

    def __new__(cls, *args, **kwargs):
        # 把位置参数和关键字参数组合成唯一键
        # 注意:kwargs转成frozenset是为了避免字典顺序影响键的唯一性
        key = (args, frozenset(kwargs.items()))
        # 缓存里没有就创建新实例并存入
        if key not in cls._instance_cache:
            cls._instance_cache[key] = super().__new__(cls)
            # 标记实例未初始化,避免重复执行__init__
            cls._instance_cache[key]._initialized = False
        
        instance = cls._instance_cache[key]
        # 只在第一次创建时执行初始化
        if not getattr(instance, '_initialized', False):
            instance.__init__(*args, **kwargs)
            instance._initialized = True
        return instance

    def __init__(self, arg1, arg2, arg3):
        self.arg1 = arg1
        self.arg2 = arg2
        self.arg3 = arg3

测试代码

arg1 = 1
arg2 = 2
arg3 = 3
arg4 = 4
arg5 = 5

instance1 = SomeClass(arg1, arg2, arg3)
instance2 = SomeClass(arg1, arg4, arg5)
instance3 = SomeClass(arg1, arg2, arg3)

print(id(instance1) == id(instance2))  # 输出 False
print(id(instance1) == id(instance3))  # 输出 True

方案二:用装饰器包装类

如果不想修改类的内部代码,可以写一个通用装饰器来实现实例缓存:

def cached_instance(cls):
    cache = {}
    def wrapper(*args, **kwargs):
        key = (args, frozenset(kwargs.items()))
        if key not in cache:
            cache[key] = cls(*args, **kwargs)
        return cache[key]
    return wrapper

# 给目标类加上装饰器
@cached_instance
class SomeClass:
    def __init__(self, arg1, arg2, arg3):
        self.arg1 = arg1
        self.arg2 = arg2
        self.arg3 = arg3

这个方案的调用方式和测试结果和上面完全一致,而且装饰器可以复用给其他类。

关于你提到的双类方案

双类(工厂类+目标类)的方式也能实现,但需要通过工厂方法调用(比如SomeClassFactory.get_instance(...)),不如上面两种方案直接,而且代码冗余度更高,所以不推荐。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 18:41:05