Singleton : There is only a single instance of the given class.
There are multiple ways to create Singleton class in python. Most of these deals with overriding Dunder methods.
Overriding __new__
When you are writing a python class, __new__
methods creates the instance of the class. So the easiest way to create a singleton class is by overriding this method.
In this method, we can check if this class has already an instance created. if yes, return that otherwise create an instance, store it in a class variable and return that variable's value.
class Singleton:
_instance = None
_initialized = False
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = object.__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self, name):
if not self._initialized:
self.name=name
self._initialized = True
Every time, you call Singleton()
, Singleton class' __new__
method is going to be called. The very first time, it will create its instance and assign to _instance. and after that it is going to return the same object.
For creating the instance, it is calling object's __new__
and not from cls.__new__
otherwise it will end up in recursion.
Object created from __new__
is then passed to __init__
function. To avoid re initialing the object, we are using a flag on instance _initialized
. Using this flag, this instance is initialized only once.
We can also use this class as a base for other Singleton classes.
The downside is , since python supports multiple inheritance, order of bases classes may mess up this behavior.
Using meta class
We know that an object is created when we call the class using () like Someclass()
Hence another place to make sure that only once instance gets created in by overriding __call__
method for this class. Where do we override the __call ?? we do that in class' class i.e. meta class.
class SingletonMeta(type):
_instance = None
def __call__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__call__( *args, **kwargs)
return cls._instance
We create a meta class (inherits type) and override __call__
. Please note that this __call__
would override the __call__
in the class which uses this meta class.
To create a singleton class using this meta class, we simply specify the meta class.
class MySingletonClass(metaclass=SingletonMeta):
pass
Every time you call MySingletonClass()
to create an object, its overridden __call__
method will be invoked which act similar to what we did with __new__
in previous approach. This approach does not have the disadvantage of inheritance.
Hopefully this gives you some ideas to create singleton class in python and also where we could meta class and various Dunder methods.
Thanks for reading.