Question or problem about Python programming:
There seem to be many ways to define singletons in Python. Is there a consensus opinion on Stack Overflow?
How to solve the problem:
Solution 1:
I don’t really see the need, as a module with functions (and not a class) would serve well as a singleton. All its variables would be bound to the module, which could not be instantiated repeatedly anyway.
If you do wish to use a class, there is no way of creating private classes or private constructors in Python, so you can’t protect against multiple instantiations, other than just via convention in use of your API. I would still just put methods in a module, and consider the module as the singleton.
Solution 2:
Here’s my own implementation of singletons. All you have to do is decorate the class; to get the singleton, you then have to use the Instance
method. Here’s an example:
@Singleton class Foo: def __init__(self): print 'Foo created' f = Foo() # Error, this isn't how you get the instance of a singleton f = Foo.instance() # Good. Being explicit is in line with the Python Zen g = Foo.instance() # Returns already created instance print f is g # True
And here’s the code:
class Singleton: """ A non-thread-safe helper class to ease implementing singletons. This should be used as a decorator -- not a metaclass -- to the class that should be a singleton. The decorated class can define one `__init__` function that takes only the `self` argument. Also, the decorated class cannot be inherited from. Other than that, there are no restrictions that apply to the decorated class. To get the singleton instance, use the `instance` method. Trying to use `__call__` will result in a `TypeError` being raised. """ def __init__(self, decorated): self._decorated = decorated def instance(self): """ Returns the singleton instance. Upon its first call, it creates a new instance of the decorated class and calls its `__init__` method. On all subsequent calls, the already created instance is returned. """ try: return self._instance except AttributeError: self._instance = self._decorated() return self._instance def __call__(self): raise TypeError('Singletons must be accessed through `instance()`.') def __instancecheck__(self, inst): return isinstance(inst, self._decorated)
Solution 3:
You can override the __new__
method like this:
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 if __name__ == '__main__': s1 = Singleton() s2 = Singleton() if (id(s1) == id(s2)): print "Same" else: print "Different"
Solution 4:
A slightly different approach to implement the singleton in Python is the borg pattern by Alex Martelli (Google employee and Python genius).
class Borg: __shared_state = {} def __init__(self): self.__dict__ = self.__shared_state
So instead of forcing all instances to have the same identity, they share state.
Solution 5:
The module approach works well. If I absolutely need a singleton I prefer the Metaclass approach.
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
Solution 6:
See this implementation from PEP318, implementing the singleton pattern with a decorator:
def singleton(cls): instances = {} def getinstance(): if cls not in instances: instances[cls] = cls() return instances[cls] return getinstance @singleton class MyClass: ...
Solution 7:
As the accepted answer says, the most idiomatic way is to just use a module.
With that in mind, here’s a proof of concept:
def singleton(cls): obj = cls() # Always return the same object cls.__new__ = staticmethod(lambda cls: obj) # Disable __init__ try: del cls.__init__ except AttributeError: pass return cls
See the Python data model for more details on __new__
.
Example:
@singleton class Duck(object): pass if Duck() is Duck(): print "It works!" else: print "It doesn't work!"
Notes:
-
You have to use new-style classes (derive from
object
) for this. -
The singleton is initialized when it is defined, rather than the first time it’s used.
-
This is just a toy example. I’ve never actually used this in production code, and don’t plan to.
Solution 8:
The Python documentation does cover this:
class Singleton(object): def __new__(cls, *args, **kwds): it = cls.__dict__.get("__it__") if it is not None: return it cls.__it__ = it = object.__new__(cls) it.init(*args, **kwds) return it def init(self, *args, **kwds): pass
I would probably rewrite it to look more like this:
class Singleton(object): """Use to create a singleton""" def __new__(cls, *args, **kwds): """ >>> s = Singleton() >>> p = Singleton() >>> id(s) == id(p) True """ self = "__self__" if not hasattr(cls, self): instance = object.__new__(cls) instance.init(*args, **kwds) setattr(cls, self, instance) return getattr(cls, self) def init(self, *args, **kwds): pass
It should be relatively clean to extend this:
class Bus(Singleton): def init(self, label=None, *args, **kwds): self.label = label self.channels = [Channel("system"), Channel("app")] ...
Solution 9:
I’m very unsure about this, but my project uses ‘convention singletons’ (not enforced singletons), that is, if I have a class called DataController
, I define this in the same module:
_data_controller = None def GetDataController(): global _data_controller if _data_controller is None: _data_controller = DataController() return _data_controller
It is not elegant, since it’s a full six lines. But all my singletons use this pattern, and it’s at least very explicit (which is pythonic).
Solution 10:
The one time I wrote a singleton in Python I used a class where all the member functions had the classmethod decorator.
class foo: x = 1 @classmethod def increment(cls, y = 1): cls.x += y