通过其对象和参数实例化 class 的单例
Singleton that instantiates a class by its object and arguments
我正在尝试准备一个单例 class,它不仅可以通过 class 类型来区分实例,还可以通过调用 class 的参数来区分实例。
假设我有一个单身人士 class,如下所示:
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
现在我正在尝试创建两个具有不同参数的 class 实例:
class MyClass(metaclass=Singleton):
def __init__(self, x, y):
print(f"Called constructor with x as {x} and y as {y}")
a = MyClass(1, 2)
b = MyClass(1, 2)
print(id(a) == id(b)) # Returns True, which is fine
c = MyClass(1, 3)
d = MyClass(1, 2)
print(id(c) == id(d)) # Returns True, which is not really fine to me :)
# Moreover y in that case is 3, not 2.
如果我想通过初始化 class 的参数来区分单例中的实例怎么办?
以下是对我有用的方法:
from dataclasses import dataclass
@dataclass(frozen=True)
class ObjectKey:
obj_type: object
args: tuple
kwargs: frozenset
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
obj_key = ObjectKey(obj_type=cls, args=args, kwargs=frozenset(kwargs.items()))
if obj_key not in cls._instances:
cls._instances[obj_key] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[obj_key]
我正在尝试准备一个单例 class,它不仅可以通过 class 类型来区分实例,还可以通过调用 class 的参数来区分实例。
假设我有一个单身人士 class,如下所示:
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
现在我正在尝试创建两个具有不同参数的 class 实例:
class MyClass(metaclass=Singleton):
def __init__(self, x, y):
print(f"Called constructor with x as {x} and y as {y}")
a = MyClass(1, 2)
b = MyClass(1, 2)
print(id(a) == id(b)) # Returns True, which is fine
c = MyClass(1, 3)
d = MyClass(1, 2)
print(id(c) == id(d)) # Returns True, which is not really fine to me :)
# Moreover y in that case is 3, not 2.
如果我想通过初始化 class 的参数来区分单例中的实例怎么办?
以下是对我有用的方法:
from dataclasses import dataclass
@dataclass(frozen=True)
class ObjectKey:
obj_type: object
args: tuple
kwargs: frozenset
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
obj_key = ObjectKey(obj_type=cls, args=args, kwargs=frozenset(kwargs.items()))
if obj_key not in cls._instances:
cls._instances[obj_key] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[obj_key]