假设我想自由地创建我的类的实例,但是如果我使用相同的参数进行实例化,我想获得表示该参数的相同唯一实例。例如:
a = MyClass('Instance 1');
b = MyClass('Instance 2');
c = MyClass('Instance 1');
根据我传入的唯一标识符,我希望a == c
为True
。
注意:
(1)我不是在谈论操纵相等运算符 - 我希望a
与c
实际上是同一个实例。
(2)这是作为库代码,因此唯一性必须强制执行 - 我们不能指望用户做正确的事情(无论是什么)。
有没有规范的方法来实现这一目标?我一直遇到这种模式,但我经常看到涉及阴影类的解决方案,仅用于内部实例化。我想我有一个更清洁的解决方案,但它确实涉及一个get()方法,我想知道我是否可以做得更好。
答案 0 :(得分:2)
我会使用元类。此解决方案避免了多次调用__init__()
:
class CachedInstance(type):
_instances = {}
def __call__(cls, *args):
index = cls, args
if index not in cls._instances:
cls._instances[index] = super(CachedInstance, cls).__call__(*args)
return cls._instances[index]
class MyClass(metaclass=CachedInstance):
def __init__(self, name):
self.name = name
a = MyClass('Instance 1');
b = MyClass('Instance 2');
c = MyClass('Instance 1');
assert a is c
assert a is not b
答案 1 :(得分:1)
可以这样做(假设args
都是可以清洗的)
class MyClass:
instances = {}
def __new__(cls, *args):
if args in cls.instances:
return cls.instances[args]
self = super().__new__(cls)
cls.instances[args] = self
return self
a = MyClass('hello')
b = MyClass('hello')
c = MyClass('world')
a is b and a == b and a is not c and a != c # True
is
是python运算符,它显示两个对象是同一个实例。 <{1}}会在未被覆盖的对象上回落到==
。
正如评论中所指出的,如果您有is
副作用,这可能会有点麻烦。这是一个避免这种情况的实现:
__init__