Yes - the metaclass's __new__
and __init__
methods are called only when the class is created. After that, in your example, the class will be bound to theMultiply
name. In many aspects, it is just an object like any other in Python. When you do objA = Multiply()
you are not creating a new instance of type(Multiply)
, which is the metaclass - you are creating a new instance of Multiply
itself: Multiply.__new__
and Multiply.__init__
are called.
Now, there is this: the mechanism in Python which make __new__
and __init__
be called when creating an instance is the code in the metaclass __call__
method. That is, just as when you create any class with a __call__
method and use an instance of it with the calling syntax obj()
will invoke type(obj).__call__(obj)
, when you do Multiply()
what is called (in this case) is Singleton.__call__(Multiply)
.
Since it is not implemented, Singleton's superclass, which is type
__call__
method is called instead - and it is in there that Multiply.__new__
and __init__
are called.
That said, there is nothing in the code above that would make your classes behave as "singletons". And more importantly you don't need a metaclass to have a singleton in Python. I don't know who invented this thing, but it keeps circulating around.
First, if you really need a singleton, all you need to do is to write a plain class, no special anything, create your single instance, and document that the instance should be used. Just as people use None
- no one keeps getting a reference to Nonetype
and keep calling it to get a None
reference:
class _Multiply:
...
# document that the code should use this instance:
Multiply = _Multiply()
second Alternatively, if your code have a need, whatsoever, for instantiating the class that should be a singleton where it will be used, you can use the class' __new__
method itself to control instantiation, no need for a metaclass:
class Multiply:
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
# insert any code that would go in `__init__` here:
...
...
return cls._instance
Third just for demonstration purposes, please don't use this, the metaclass mechanism to have singletons can be built in the __call__
method:
class Singleton(type):
registry = {}
def __new__(mcls,name,bases,attr):
print(f"name {name}")
print(f"bases {bases}")
print(f"attr {attr}")
print("Class created")
print ("Space Please")
return super(Singleton,mcls).__new__(cls,name,bases,attr)
def __call__(cls, *args, **kw):
registry = type(cls).registry
if cls not in registry:
print(f"{cls.__name__} being instantiated for the first time")
registry[cls] = super().__call__(*args, **kw)
else:
print(f"Attempting to create a new instance of {cls.__name__}. Returning single instance instead")
return registry[cls]
class Multiply(metaclass = Singleton):
pass