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