Why foo is printed twice?
class A:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, *, var):
print('foo')
self.var = var
a = A(var=1)
b = A(var=2)
assert a == b
assert a.var == b.var
When you write A(...), you are calling
type.__call__(A, ...)
That's because type is the metaclass of A. type.__call__ will call __new__ and __init__ in sequence. __init__ will always be called if __new__ returns an instance of the class. Here is a simplified view:
def __call__(cls, *args, **kwargs):
self = cls.__new__(cls, *args, **kwargs)
if isinstance(self, cls):
cls.__init__(self, *args, **kwargs)
return self
The simplest way I can think of making a singleton work this way is to put all your initialization logic into __new__:
class A:
_instance = None
def __new__(cls, *, var):
if cls._instance is None:
self = super().__new__(cls)
self.var = var
cls._instance = self
return cls._instance
def __init__(self, *args, **kwargs):
print('foo')
Sure, foo still gets printed every time you ask for a new instance, but it's well and truly a singleton.
A more comprehensive approach is to override the behavior of your metaclass __call__ method. That will avoid calling __init__ except once:
class Singleton(type):
def __call__(cls, *args, **kwargs):
if hasattr(cls, '_instance'):
return cls._instance
return super().__call__(*args, **kwargs)
class A(metaclass=Singleton):
def __init__(self, *, var):
print('foo')
self.var = var
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