How to create a singleton in Python using a metaclass
In this tutorial, we will learn how to create a singleton in Python using a metaclass.
What is a singleton?
Well, a singleton is a creational pattern that ensures that there can exist only one object of its kind. This way, it can only be accessed through a single point.
There are many ways to create a singleton i.e. decorators, base class, metaclasses, etc. We are going to see how we can create a singleton using a metaclass.
Create a singleton in Python using a metaclass
We can use a metaclass to create a singleton in Python. In the given example program we have created a metaclass with name SingletonMeta which overrides the __call__() method and manipulates it in such a way that there can never be more than one instance for a class that is an instance of this class. Then we create an instance of SingletonMeta class with the name Singleton as shown below in the code. The Singleton class is a singleton and there can never exist two different objects of this class. Hence its attributes and methods can only be accessed through a single point.
See the code for a better understanding.
class SingletonMeta(type): _instance = {} def __call__(cls, *args, **kwargs): if cls not in cls._instance: cls._instance[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs) return cls._instance[cls] class Singleton(metaclass = SingletonMeta): pass
Now to check whether our code is right or not let’s try to create objects for this class and print them out. Here it is.
if __name__ == "__main__": singleton1 = Singleton() print(singleton1) singleton2 = Singleton() print(singleton2)
After executing the code we get something like this,
<__main__.Singleton object at 0x0000017AB25A3C88> <__main__.Singleton object at 0x0000017AB25A3C88>
It’s very clear from the output that both the objects have the same instance. Which proves our code is right.
Thank you.
Also read:
This solution is not correct. It creates a dictionary instance as a (meta)class attribute, while a per class attribute is required. This solution collects all classes using this metaclass in a dictionary and needs an expensive lookup, while a single direct attribute access could be used.
Patric Lehman, indeed this is not singleton at all 😀