Singleton class in Python

Singleton class in Python

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.