某些属性

时间:2018-06-12 15:23:57

标签: python

假设我想自由地创建我的类的实例,但是如果我使用相同的参数进行实例化,我想获得表示该参数的相同唯一实例。例如:

a = MyClass('Instance 1');
b = MyClass('Instance 2');
c = MyClass('Instance 1');

根据我传入的唯一标识符,我希望a == cTrue

注意:

(1)我不是在谈论操纵相等运算符 - 我希望ac实际上是同一个实例。

(2)这是作为库代码,因此唯一性必须强制执行 - 我们不能指望用户做正确的事情(无论是什么)。

有没有规范的方法来实现这一目标?我一直遇到这种模式,但我经常看到涉及阴影类的解决方案,仅用于内部实例化。我想我有一个更清洁的解决方案,但它确实涉及一个get()方法,我想知道我是否可以做得更好。

2 个答案:

答案 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

参考和详细说明:https://stackoverflow.com/a/6798042/8747

答案 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__