0

For this class:

Class A():
    def __init__(a, b, c=3):
        pass

I want it to return the same cached object for the same initialization arguments. Meaning:

a1 = A(1,2,3)
a2 = A(a = 1, b = 2, c = 3)
a3 = A(1, b = 2, c = 3)
a4 = A(1, b = 2)
b1 = A(1,2,4)

assert a1 is a2 is a3 is a41
assert not a1 is b1

I have this implementation of a singleton (as a metaclass):

class ThreadedSingleton(type):
""" Common singleton implementation with multi thread support. From https://stackoverflow.com/a/50567397. """
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            with lock:
                if cls not in cls._instances:
                    cls._instances[cls] = super(ThreadedSingleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

Which gives me the same object every time, but does it regardless of the parameters.

Any ideas?

martineau
  • 119,623
  • 25
  • 170
  • 301
omer mazig
  • 965
  • 2
  • 10
  • 17

1 Answers1

0

I guess a rough idea would be to cache input params:

class A:
    _cache = {}

    def __init__(self, a, b, c=3):
        self.a = a
        self.b = b
        self.c = c

    def __new__(cls, a, b, c=3, *args, **kwargs):
        key = (a, b, c)
        if key in cls._cache:
            return cls._cache[key]

        instance = cls._cache[key] = super(A, cls).__new__(cls)
        return instance

    

a1 = A(1, 2, 3)
a2 = A(a=1, b=2, c=3)
a3 = A(1, b=2, c=3)
a4 = A(1, b=2)
b1 = A(1, 2, 4)

assert a1 is a2 is a3 is a4
assert a1 is not b1
funnydman
  • 9,083
  • 4
  • 40
  • 55
  • You "corrected" the first `assert` — which has typo in OP's code — without mentioning it. If you had instead changed it to `assert a1 is a2 is a3 is a4` an `AssertionError` would have been raised and a second instance of `A` with the same arguments would have been created. – martineau Aug 01 '22 at 18:00
  • Oh, yes. You're right. I didn't notice that. Thanks for pointing this out. I've updated my answer (still not the best option and looks a bit hacky). – funnydman Aug 01 '22 at 18:16