Implementing the Singleton Pattern in Python

TL;DR: Use metaclasses - see #4 on the list

I recently heard some people at work talking about ways to implement the Singleton pattern in Python. I’m fairly new to Python, and for me, the most elegant Singleton definition would be in Java:

enum MySingleton {
    INSTANCE;

    // methods, members, etc.
}

and that’s it! Use MySingleton.INSTANCE and you got yourself a singleton. Well, in Python it’s more cumbersome (enums in Java are pretty awesome and hard to compete with, even with Python’s general awesomeness). I suggested using a singleton metaclass, but it was turned down for being too complicated. Well, let’s take a look at some other implementation ideas I’ve heard, and we’ll look at the metaclass alternative at the end:

  1. Provide a get_instance method and make __init__ throw (fine, fine, raise) an exception if it was called twice:
class MySingleton(object):
     INSTANCE = None

     def __init__(self):
        if self.INSTANCE is not None:
            raise ValueError("An instantiation already exists!")
        # do your init stuff

     @classmethod
     def get_instance(cls):
        if cls.INSTANCE is None:
             cls.INSTANCE = MySingleton()
        return cls.INSTANCE

Cons: Using get_instance is ugly and non-intuitive.

  1. Implementing an inner class as your ‘main class’ and the external one as a wrapper:
class MySingleton:     
""" A python singleton """
     class __impl:
     """ Implementation of the singleton interface """
         # implement your stuff in here
         pass

    # storage for the instance reference
    __instance = None

    def __init__(self):
        """ Create singleton instance """
        # Check whether we already have an instance
        if MySingleton.__instance is None:
            # Create and remember instance
            MySingleton.__instance = MySingleton.__impl()

        # Store instance reference as the only member in the handle
        self.__dict__[''_Singleton__instance''] = MySingleton.__instance

    def __getattr__(self, attr):
        """ Delegate access to implementation """
        return getattr(self.__instance, attr)

    def __setattr__(self, attr, value):
        """ Delegate access to implementation """
        return setattr(self.__instance, attr, value) 

Cons: This implementation is definitely not beautiful. Also, it prevents users from subclassing the business logic class.

  1. Implementing a ‘singleton’ decorator for classes:
def singleton(cls):
    instances = {}
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance @singleton class MyClass:
    ... 

Cons: This code turns MyClass into a factory function, so you can’t subclass it or use ‘isinstance’, etc.

  1. Implementing a SingletonType metaclass:
class SingletonType(type):
    def __call__(cls, *args, **kwargs):
        try:
            return cls.__instance
        except AttributeError:
            cls.__instance = super(SingletonType, cls).__call__(*args, **kwargs)
            return cls.__instance

class MySingleton(object):
    __metaclass__ = SingletonType

     # ... 

Cons: Other than some people considering metaclasses to be black magic, none that I can think of (besides general ‘singletons are evil’ complaints).

Sources

Discuss this post at the comment section below.
Follow me on Twitter , Facebook or Google+

Similar Posts