Use decorators to convert any Python class to a Singleton
In Python there are many ways to implement the Singleton Pattern. For example:
- Modules are singletons in Python.
- You could use java-like implementation, combined with factory method.
There is another interesting pythonic way to turn any class into a singleton. You could use a Python decorator and apply it to the class you want to be a singleton.
Probably more pythonic would be to use a meta class to create a singleton. This is another story. I will tell you this story soon.
Python Singleton Decorator
The decorator is changing the way new objects are created from the decorated class. Each time you are requesting a new object, you will get the same object again and again.
Here is the definition of the singleton decorator:
from functools import wraps
orig_new = orig_cls.__new__
instance = None
def __new__(cls, *args, **kwargs):
if instance is None:
instance = orig_new(cls, *args, **kwargs)
orig_cls.__new__ = __new__
Here is an example usage:
logger1 = Logger()
logger2 = Logger()
assert logger1 is logger2
In this example we have a simple
Logger class with a single method
log which logs a message. For simplicity our implementation is just printing the message to the standard output.
We are creating two
Logger objects -
logger2 we verify that the two variables are actually referring to the same object, using the
Try it out
Here is a Jupyter notebook I created as GitHub gist. You can use this notebook to try the above example.
How the singleton decorator works?
This solution is based on the way Python creates new instances of a class. When a new instance is to be created, the special method of the class, called
__new__, is called to create the instance. The method should return the newly created instance. In this solution the decorator is overwriting the original
__new__ method of the class so that it will return same instance each time it is called.
When you add a decorator to a class, the decorator function is called once, receiving as a first argument the decorated class. The decorator stores a reference to the original
__new__ method of the decorated class into a variable named
orig_new, the original
__new__ method is replaced with different implementation.
The new implementation of the
__new__ method is checking if an instance of the class has already been created. If this is the first call to the function the
instance variable is not set. The original method referenced by the
orig_new variable is called to create the initial instance of the class. The object is stored in in the
instance variable and is returned as a result from the function.
Further calls to the function will not create new instances, but will directly return the initial instance, stored in the
A little bit more advanced implementation of the Singleton pattern would be to have named object instances. For example, you might want to have different loggers. For example:
Logger('database')returns an instance for logging database messages.
Logger('http')returns an instance for logging HTTP requests.
- You can learn more about the way the
__new__method works in the Python documentation.
Published originally on my blog: Convert a Python class to Singleton using decorator