Python类实例因某些属性而唯一

2024-05-15 13:02:25 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

我希望a == cTrue,基于我传入的唯一标识符。你知道吗

注:

(1)我不是在说操纵相等运算符--我希望ac是同一个实例。你知道吗

(2)这是作为库代码使用的,因此必须执行唯一性—我们不能指望用户做正确的事情(不管是什么)。你知道吗

有没有一个规范的方法来实现这一点?我经常遇到这种模式,但我通常会看到涉及影子类的解决方案,这意味着只用于内部实例化。我想我有一个更干净的解决方案,但它确实涉及get()方法,我想知道我是否可以做得更好。你知道吗


Tags: 实例方法instance代码用户规范true参数
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

这是可以做到的(假设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操作符。==在对象上回退到is,在对象上它没有被覆盖。你知道吗


正如在评论中指出的,如果你有副作用的__init__,这可能会有点麻烦。下面是一个可以避免这种情况的实现:

class Coord:

     num_unique_instances = 0
     _instances = {}

     def __new__(cls, x, y):

         if (x, y) in cls._instances:
              return cls._instances[x, y]

         self = super().__new__(cls)

         # __init__ logic goes here    will only run once
         self.x = x
         self.y = y
         cls.num_unique_instances += 1
         # __init__ logic ends here

         cls._instances[x, y] = self
         return self

     # no __init__ method

相关问题 更多 >