Skip to content

Convert a Python class to Singleton using decorator

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

def singleton(orig_cls):
    orig_new = orig_cls.__new__
    instance = None

    @wraps(orig_cls.__new__)
    def __new__(cls, *args, **kwargs):
        nonlocal instance
        if instance is None:
            instance = orig_new(cls, *args, **kwargs)
        return instance
    orig_cls.__new__ = __new__
    return orig_cls

Here is an example usage:

@singleton
class Logger:
    def log(msg):
        print(msg)

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 - logger1 and logger2 we verify that the two variables are actually referring to the same object, using the assert statement.

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 namedorig_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 instance variable.

Discussion

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.

Further Reading