I have a few classes that need to do the following:
When the constructor is called, if an equal object (aka an object with the same id) already exists, return that object. Otherwise, create a new instance. Basically,
>>> cls(id=1) is cls(id=1)
True
To achieve this, I've written a class decorator like so:
class Singleton(object):
def __init__(self, cls):
self.__dict__.update({'instances': {},
'cls': cls})
def __call__(self, id, *args, **kwargs):
try:
return self.instances[id]
except KeyError:
instance= self.cls(id, *args, **kwargs)
self.instances[id]= instance
return instance
def __getattr__(self, attr):
return getattr(self.cls, attr)
def __setattr__(self, attr, value):
setattr(self.cls, attr, value)
This does what I want, but:
@Singleton
class c(object):
def __init__(self, id):
self.id= id
o= c(1)
isinstance(o, c) # returns False
How can I fix this? I found a related question, but I just can't seem to adapt those solutions to my use case.
I know someone's gonna ask me to post some code that doesn't work, so here you go:
def Singleton(cls):
instances= {}
class single(cls):
def __new__(self, id, *args, **kwargs):
try:
return instances[id]
except KeyError:
instance= cls(id, *args, **kwargs)
instances[id]= instance
return instance
return single
# problem: isinstance(c(1), c) -> False
def Singleton(cls):
instances= {}
def call(id, *args, **kwargs):
try:
return instances[id]
except KeyError:
instance= cls(id, *args, **kwargs)
instances[id]= instance
return instance
return call
# problem: isinstance(c(1), c) -> TypeError
You can add your custom __instancecheck__
hook in your decorator class:
def __instancecheck__(self, other):
return isinstance(other, self.cls)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With