First, I don’t want to go into why/when to use Singletons (Or even if they have a valid use in python)… And yes, they do tend to be confusing no matter how they are implemented.
After looking around a bit, I wasn’t happy with many of the ways of creating a “singleton” in python, they all had some major flaw (That affected how I wanted to use it anyways).
Here’s the ways that I found while researching and my issues with them..
class Singleton(type): def __init__(cls, name, bases, dict): super(Singleton, cls).__init__(name, bases, dict) cls.instance = None def __call__(cls,*args,**kw): if cls.instance is None: cls.instance = super(Singleton, cls).__call__(*args, **kw) return cls.instance class MyClass(object): __metaclass__ = Singleton
My main problem with this method is that PyQt doesn’t allow for __metaclass__ because sip already defines a __metaclass__ for all PyQt objects. Otherwise this method seems fairly clean (Although metaclasses do seem to confuse many python users)
class Singleton(object): _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super(Singleton, cls).__new__( cls, *args, **kwargs) return cls._instance
This one has a fairly glaring issue, and I don’t know why so many people recommend it.. This variant ends up with __init__ being called EVERY time you access it via Singleton(), which causes all sorts of issues. (You could track if __init__ has already run, but that’s even more crap your Singleton has to hack around in your class)
Creating a wrapper class (Too long to post here, here’s the recipe link):
this variant just seems messy to me, anytime __getattr__ and __setattr__ are being overwritten, there’s typically a better way (Not always of course).
Just raising an exception ( O.o ):
class Singleton: __single = None def __init__( self ): if Singleton.__single: raise Singleton.__single Singleton.__single = self
Well that’s just not what most people want… if you don’t have access to where the current instance is stored, you now have to understand how the singleton is implemented and access Singleton.__single in order to get it… Yuck.
It also means you have to check whenever you need it for an exception.
Overwriting itself and using __call__
class Singleton: def __call__(self): return self Singleton = Singleton()
I like how simple this variant is, it certainly seems closer to what I want. The issue with this singleton is that it can’t be subclassed, but otherwise it seems like fairly elegant python.
(You could subclass by using Singleton.__class__ I suppose, but that means other people subclassing you have to be aware of it. And their class won’t automatically behave like a singleton without them also overwriting their own name as well)
My version (Overwrite itself only on __init__):
class Singleton(object): def __init__(self): globals()[self.__class__.__name__] = self def __call__(self): return self
Subclasses don’t have to know about how the singleton is implemented, as long as the call the parent __init__ they will be a singleton as well (Even in another module):
class SubSingleton(Singleton): def __init__(self): super(SubSingleton, self).__init__()
And there you have it (If you want it anyways…)
No issues with subclassing, since at declaration time (And all the way up until Singleton() is called) your object is still the class, not the instance.
init is only called once, as it should be. And no metaclass is used, so PyQt is happy.
References from my research: