39

I'd like to implement some sort of singleton pattern in my Python program. I was thinking of doing it without using classes; that is, I'd like to put all the singleton-related functions and variables within a module and consider it an actual singleton.

For example, say this is to be in the file 'singleton_module.py':

# singleton_module.py

# Singleton-related variables
foo = 'blah'
bar = 'stuff'

# Functions that process the above variables
def work(some_parameter):
    global foo, bar
    if some_parameter:
        bar = ...
    else:
        foo = ...

Then, the rest of the program (i.e., other modules) would use this singleton like so:

# another_module.py

import singleton_module

# process the singleton variables,
# which changes them across the entire program
singleton_module.work(...)

# freely access the singleton variables
# (at least for reading)
print singleton_module.foo

This seemed to be a pretty good idea to me, because it looks pretty clean in the modules that use the singleton.

However, all these tedious 'global' statements in the singleton module are ugly. They occur in every function that processes the singleton-related variables. That's not much in this particular example, but when you have 10+ variables to manage across several functions, it's not pretty.

Also, this is pretty error-prone if you happen to forget the global statements: variables local to the function will be created, and the module's variables won't be changed, which is not what you want!

So, would this be considered to be clean? Is there an approach similar to mine that manages to do away with the 'global' mess?

Or is this simply not the way to go?

  • Why do you need a singleton in the first place. It seems that 90% of the people who think they want/need a singleton really don't. –  Jun 06 '11 at 16:28
  • 2
    Well, of course I don't really *need* a singleton. I used to use a class and it worked just fine, but I thought, since I only ever have one instance of this particular class, couldn't I make it a singleton? –  Jun 06 '11 at 16:32
  • Well, since you already figured out one problem with the singleton, I'd say the class wins ;) –  Jun 06 '11 at 16:36
  • One could argue that if you _do_ need a singleton - the less state it has, the better. If you end up with too many `global`s, maybe that's also a sign of bad design? Also see http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons :) – André Laszlo Jan 09 '15 at 20:46

6 Answers6

29

A common alternative to using a module as a singleton is Alex Martelli's Borg pattern:

class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state
    # and whatever else you want in your class -- that's all!

There can be multiple instances of this class, but they all share the same state.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • 1
    [Alex](http://stackoverflow.com/users/95810/alex-martelli) seems to have disappeared from SO -- he hasn't been seen since last November! 8v( – Fred Larson Jun 06 '11 at 16:54
  • Do you mean multiple variables referring to same instance or multiple instances all sharing same state ? Can you please clarify ? – Jaydev Sep 14 '16 at 17:20
  • 1
    @Jaydev I mean what I said – multiple instances sharing the same state. The `__shared_state` dictionary is a class variable, so all instances of the class share their state. – Sven Marnach Sep 17 '16 at 21:11
7

Maybe you can put all the variables in a global dict, and you can directly use the dict in your functions without "global".

# Singleton-related variables
my_globals = {'foo': 'blah', 'bar':'stuff'}

# Functions that process the above variables
def work(some_parameter):
    if some_parameter:
        my_globals['bar'] = ...
    else:
        my_globals['foo'] = ...

why you can do it like this is Python Scopes and Namespaces.

WillYang
  • 71
  • 1
  • 1
1

One approach to implementing a singleton pattern with Python can also be:

have singleton __init()__ method raise an exception if an instance of the class already exists. More precisely, class has a member _single. If this member is different from None, exception is raised.

class Singleton:
    __single = None
    def __init__( self ):
        if Singleton.__single:
            raise Singleton.__single
        Singleton.__single = self  

It could be argued that handling the singleton instance creation with exceptions is not very clean also. We may hide implementation details with a method handle() as in

def Handle( x = Singleton ):
    try:
        single = x()
    except Singleton, s:
        single = s
    return single 

this Handle() method is very similar to what would be a C++ implementation of the Singleton pattern. We could have in Singleton class the handle()

Singleton& Singleton::Handle() {

  if( !psingle ) {
    psingle = new Singleton;
  }
  return *psingle;
}

returning either a new Singleton instance or a reference to the existing unique instance of class Singleton.

Handling the whole hierarchy

If Single1 and Single2 classes derive from Singleton, a single instance of Singleton through one of the derived class exists. This can be verify with this:

>>> child = S2( 'singlething' )
>>> junior = Handle( S1)
>>> junior.name()
'singlething'
kiriloff
  • 25,609
  • 37
  • 148
  • 229
0

Building off of WillYang's answer and taking it a step further for cleanliness: define a simple class to hold your global dictionary to make it easier to reference:

class struct(dict):
    def __init__(self, **kwargs):
        dict.__init__(self, kwargs)
        self.__dict__ = self

g = struct(var1=None, var2=None)

def func():
    g.var1 = dict()
    g.var3 = 10
    g["var4"] = [1, 2]
    print(g["var3"])
    print(g.var4)

Just like before you put anything you want in g but now it's super clean. :)

Community
  • 1
  • 1
Adam S.
  • 323
  • 3
  • 10
0

For a legitimate Singleton:

class SingletonMeta(type):
    __classes = {} # protect against defining class with the same name
    def __new__(cls, cls_name, cls_ancestors, cls_dict): 
         if cls_name in cls.__classes:
             return cls.__classes[cls_name]
         type_instance = super(SingletonMeta, cls).__new__(cls, cls_name, cls_ancestors, cls_dict) # pass 'type' instead of 'cls' if you dont want SingletonMeta's attributes reflected in the class
         return type_instance() # call __init__

class Singleton:
    __metaclass__ = SingletonMeta
    # define __init__ however you want

    __call__(self, *args, *kwargs):
        print 'hi!'

To see that it truly is a singleton, try to instantiate this class, or any class that inherits from it.

singleton = Singleton() # prints "hi!"
Michael Ward
  • 496
  • 5
  • 13
0

Similar to Sven's "Borg pattern" suggestion, you could just keep all your state data in a class, without creating any instances of the class. This method utilizes new-style classes, I believe.

This method could even be adapted into the Borg pattern, with the caveat that modifying the state members from the instances of the class would require accessing the __class__ attribute of the instance (instance.__class__.foo = 'z' rather than instance.foo = 'z', though you could also just do stateclass.foo = 'z').

class State:    # in some versions of Python, may need to be "class State():" or "class State(object):"
    __slots__ = []   # prevents additional attributes from being added to instances and same-named attributes from shadowing the class's attributes
    foo = 'x'
    bar = 'y'

    @classmethod
    def work(cls, spam):
        print(cls.foo, spam, cls.bar)

Note that modifications to the class's attributes will be reflected in instances of the class even after instantiation. This includes adding new attributes and removing existing ones, which could have some interesting, possibly useful effects (though I can also see how that might actually cause problems in some cases). Try it out yourself.

JAB
  • 20,783
  • 6
  • 71
  • 80