Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python and the Singleton Pattern [duplicate]

There seem to be many ways to define singletons in Python. Is there a consensus opinion on Stack Overflow?

like image 963
Jamie Avatar asked Aug 28 '08 09:08

Jamie


People also ask

Does Python support singleton?

A Singleton pattern in python is a design pattern that allows you to create just one instance of a class, throughout the lifetime of a program. Using a singleton pattern has many benefits.

How does singleton work in Python?

Singleton is a creational design pattern, which ensures that only one object of its kind exists and provides a single point of access to it for any other code. Singleton has almost the same pros and cons as global variables. Although they're super-handy, they break the modularity of your code.

Is Python logging a singleton?

Singleton Logging ServiceLogging service that is guaranteed to be a singleton. Based on Python logging, but every instantiation of LoggingService from any of an application's modules returns the same logger instance.

What is the disadvantage of Singleton design pattern?

Disadvantages of a Singleton PatternUnit testing is more difficult (because it introduces a global state into an application). This pattern reduces the potential for parallelism within a program, because to access the singleton in a multi-threaded system, an object must be serialized (by locking).


14 Answers

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.

like image 138
Staale Avatar answered Oct 03 '22 02:10

Staale


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)
like image 43
Paul Manta Avatar answered Oct 03 '22 02:10

Paul Manta


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"
like image 42
jojo Avatar answered Oct 03 '22 04:10

jojo


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.

like image 34
Peter Hoffmann Avatar answered Oct 03 '22 03:10

Peter Hoffmann


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
like image 33
Acuminate Avatar answered Oct 03 '22 04:10

Acuminate


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:
    ...
like image 41
Wei Avatar answered Oct 03 '22 03:10

Wei


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
        """
        it_id = "__it__"
        # getattr will dip into base classes, so __dict__ must be used
        it = cls.__dict__.get(it_id, None)
        if it is not None:
            return it
        it = object.__new__(cls)
        setattr(cls, it_id, it)
        it.init(*args, **kwds)
        return it

    def init(self, *args, **kwds):
        pass


class A(Singleton):
    pass


class B(Singleton):
    pass


class C(A):
    pass


assert A() is A()
assert B() is B()
assert C() is C()
assert A() is not B()
assert C() is not B()
assert C() is not A()

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")]
        ...
like image 44
Brian Bruggeman Avatar answered Oct 03 '22 03:10

Brian Bruggeman


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:

  1. You have to use new-style classes (derive from object) for this.

  2. The singleton is initialized when it is defined, rather than the first time it's used.

  3. This is just a toy example. I've never actually used this in production code, and don't plan to.

like image 39
Lambda Fairy Avatar answered Oct 03 '22 03:10

Lambda Fairy


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).

like image 45
u0b34a0f6ae Avatar answered Oct 03 '22 03:10

u0b34a0f6ae


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
like image 37
David Locke Avatar answered Oct 03 '22 04:10

David Locke


Creating a singleton decorator (aka an annotation) is an elegant way if you want to decorate (annotate) classes going forward. Then you just put @singleton before your class definition.

def singleton(cls):
    instances = {}
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance

@singleton
class MyClass:
    ...
like image 14
Matt Alcock Avatar answered Oct 03 '22 03:10

Matt Alcock


There are also some interesting articles on the Google Testing blog, discussing why singleton are/may be bad and are an anti-pattern:

  • Singletons are Pathological Liars
  • Where Have All the Singletons Gone?
  • Root Cause of Singletons
like image 9
FrankS Avatar answered Oct 03 '22 02:10

FrankS


I think that forcing a class or an instance to be a singleton is overkill. Personally, I like to define a normal instantiable class, a semi-private reference, and a simple factory function.

class NothingSpecial:
    pass

_the_one_and_only = None

def TheOneAndOnly():
    global _the_one_and_only
    if not _the_one_and_only:
        _the_one_and_only = NothingSpecial()
    return _the_one_and_only

Or if there is no issue with instantiating when the module is first imported:

class NothingSpecial:
    pass

THE_ONE_AND_ONLY = NothingSpecial()

That way you can write tests against fresh instances without side effects, and there is no need for sprinkling the module with global statements, and if needed you can derive variants in the future.

like image 8
Mark Evans Avatar answered Oct 03 '22 04:10

Mark Evans


The Singleton Pattern implemented with Python courtesy of ActiveState.

It looks like the trick is to put the class that's supposed to only have one instance inside of another class.

like image 3
Mark Biek Avatar answered Oct 03 '22 03:10

Mark Biek