Implementing the Singleton Pattern in Python
I would still love to hear your feedback in the comments below. Enjoy!
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:
- 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.
- 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.
- 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.
- 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 and Facebook