Welcome, guest | Sign In | My Account | Store | Cart
15

The Singleton design pattern (DP) has a catchy name, but the wrong focus -- on identity rather than on state. The Borg design pattern has all instances share state instead, and Python makes it, literally, a snap.

Python, 5 lines
1
2
3
4
5
class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state
    # and whatever else you want in your class -- that's all!

The 'Singleton' DP is all about ensuring that just one instance of a certain class is ever created. It has a catchy name and is thus enormously popular, but it's NOT a good idea -- it displays different sorts of problems in different object-models. What we should really WANT, typically, is to let as many instances be created as necessary, BUT all with shared state. Who cares about identity -- it's state (and behavior) we care about!

You can ensure this in many ways in Python, but the Borg design pattern is almost always best. Since the self.__dict__ of any instance can be re-bound, just re-bind it in __init__ to a class-attribute dictionary -- that's all! Now any reference or binding of an instance attribute will actually affect all instances equally -- "we all are one", and all that jazz. Thanks to David Ascher for suggesting the very appropriate name "Borg" for this DP.

Note that __getattr__ and __setattr__ are not involved -- they can be defined independently for whatever other purposes, or left undefined (and __setattr__, if defined, is NOT called for the rebinding of __dict__ itself). This only works with 'classic classes' (all classes in Python 2.1 and earlier, those that don't inherit from built-in types in 2.2 and later), whose instances keep all their per-instance state via self.__dict__ -- 2.2/+ classes with self.__slots__ do not support this idiom quite as smoothly (you can use getters/setters for such advanced-classes to deal with this issue, if you wish, but sticking to 'classic classes' for these needs may be simplest).

31 comments

Magnus Lie Hetland 14 years, 11 months ago  # | flag

Another name... How about Hivemind? I've seen that used in science fiction situations that might fit this concept

David Ascher 14 years, 11 months ago  # | flag

Name suggestion. I think the 'Borg' fits this pattern quite well. =)

Marcus Baker 14 years, 11 months ago  # | flag

Should just call it a singleton! The singleton name is correct, even though your Python implementation is neat++.

In Effective C++ by Scott Meyers (item 47) he solves the singleton problem in exactly the same way. The object is created once and then subsquent calls simply return a reference to the original object. In C++ Meyers uses a function wrapper to ensure that it will be declared early enough, but the principle is the same.

In the Design Patterns book the C++ implementation has a class wide Singleton::Instance() function and prevents the constructor being used by making it protected. Same trick.

Coincidently, in an upcoming PHP cookbook web site I am going to publish a singlton pattern that uses the same trick.

yours, Marcus.

Alex Martelli (author) 14 years, 11 months ago  # | flag

It's NOT a singleton object... it doesn't NEED to be! This is a completely and deeply different pattern from Singleton, and thus I find the latest comment totally off-base. Singleton focuses (wrongly) on object IDENTITY: that's what the Gof4 focuses on, that's what "EffC++" focuses on, etc, etc. But we don't really care about identity most of the time, but about state and behavior.

The "Borg" design pattern IS quite possible in C++ (just a bit more laborious, but not much) and was indeed once written up in C++ Report (but I forget the name it was given then and can't find my old issue): you get as many objects as you want, with separate identities but all sharing state and behavior. That's the POINT! Just about all the practical USEFULNESS of Singleton without the troublesome identity-issue that Singleton tends to give.

dani kenan 14 years, 11 months ago  # | flag

You loose the encapsulation, readability and explicitness offered by the Singleton. You have a point with the state thing and all, however you do loose the encapsulation offered by the Singleton pattern. You also loose readability and explicitness.

If you take the gof course, your implementation can still return new instances implemented just as you have described.

However, if you take your course it will be much difficult (or impossible) to replace the creation of new instances with a single one.

Also, you loose the explicitness offered by the gof pattern. Clients know that they use a shared object and that it is – transient – and susceptible to change by others.

Your suggestion might lead to serious misunderstandings (i.e. bugs) in clients of the object (and the external interface exposed to the client is more important than the implementation and the implementers).

Marcus Baker 14 years, 11 months ago  # | flag

quoting... Please calm down.

From GOF4: "...to make the class itself responsible for keeping track of it's sole instance." which does cover your intention.

I probably did not make clear that it was their intention rather than their implementation I was trying to get accross. EffC++ was trying to solve a slightly different problem and recast it as a singleton. It seems pretty clear that both were trying to get around the "new" semantics in their implementations and that your implementation is different. Agreed.

Singleton is a very nice name. Agreed.

Borg is a nice name, but I am not sure that it is exactly right. It could fit a lot of cooperative behaviours as well as "all as one". A thread pool that all worked at the same task would fit.

I could not say which is the more confusing and you will have to just ask lots of programmers as a usability test. I am afraid my personal vote is still for singleton as when I inherit a singleton I know what I want, but when I inherit a Borg I am (a little) less sure.

Please let us know which issue of C++ report it is in when you find it.

yours, Marcus.

Alex Martelli (author) 14 years, 11 months ago  # | flag

inheriting singleton vs inheriting borg. What happens in a large system when two separate subsystems both inherit from (extend) a singleton-class? It's anything but clear to me -- error at runtime, at compiletime, at linktime (none such in Python, let's say at import-time), or what behavior...?

With Borg, it's simplicity itself: as Borg can be instantiated as many times as you want, but all instances share state, each separate subclass may differently override _behavior_, but _state_ will still be collectively shared by all Borg's and sub-Borg's. (Separate sub-Borg classes may of course have class-private state by naming attributes with two leading underscores, as typically done in Python). Easy as pie -- and by that very token, easy to document and explain, too. "All state is shared, identity is indifferent, you'll be assimilated"!-)

Steve Holden 14 years, 10 months ago  # | flag

This discussion ... ... is getting very long and thin (at least in my browser).

Perhaps additional remarks could appear in a new thread?

Nicola Musatti 14 years, 10 months ago  # | flag

Borg vs. Singleton. Alex, isn't this pattern the one you once referred to as "Stateless Proxy"? And, Marcus, Borg is similar to Singleton, except that you separate access and functionality. In C++ you'd still have a static instance of the class that provides the functionality (no loss of encapsulation, then), but it would be private to the Borg class and would only be accessed by the Borg class's member functions.

Alex Martelli (author) 14 years, 10 months ago  # | flag

Borg is indeed 'stateless proxy' Yes Nicola, Borg is the new and improved name (suggested by David Ascher, chief editor of this Cookbook, in a comment above) for the pattern formerly known as 'stateless proxy'.

Dale Nagata 14 years, 10 months ago  # | flag

also known as Monostate. There was an article in the C++ Report several years ago that introduced the Monostate pattern, where all instances share the same state.

The major problem I have found with most implementations of Singletons or Monostates in various languages is that if you need to support multithreading, you have to jump through some fairly major hoops to achieve a good balance of correctness and efficiency.

Dale Nagata 14 years, 10 months ago  # | flag

also known as Monostate. There was an article in the C++ Report several years ago that introduced the Monostate pattern, where all instances share the same state.

The major problem I have found with most implementations of Singletons or Monostates in various languages is that if you need to support multithreading, you have to jump through some fairly major hoops to achieve a good balance of correctness and efficiency.

Jan Wender 14 years, 9 months ago  # | flag

Borg and more than one module. If you want to use the Borg pattern from more than one module, it works as follows: Extract the Borg Pattern into a module and a class of its own: borg.py:

class Borg:
    __shared_state = {} # or org.python.core.PyStringMap in jython
    def __init__(self):
         self.__dict__ = self.__shared_state

Let your class in a separate module inherit from Borg and call Borg's initializer in your __init__:

import borg
class Test(borg.Borg):
  def __init__(s):
     borg.Borg.__init__(s)

Although sounding like a swedish chef, it works now. The state is shared across all modules using the Test class.

Jan Wender 14 years, 9 months ago  # | flag

Sorry for the replication. Must've hit add instead of preview somewhere...

Jan Wender 14 years, 9 months ago  # | flag

Although it looks now like a bug in the Cookbook code... I'm sure I added the last comment only once!

Alex Martelli (author) 14 years, 9 months ago  # | flag

threading. Threading issues really have little to do with Highlander vs Borg (or Singleton vs Monostate if you prefer boring names:-). In Python, it's simplest to devote a thread to handling a bunch of resources that need to be serialized (no matter whether they're wrapped into one or more objects of whatever type), with a Queue of requests on which the devoted-thread (Guardian thread) always sleeps working for requests. All access by working threads to the guardian thread and the resources it protects is by posting to the guardian queue a tuple (response-queue, callable, args, kwds) followed by waiting on the response-queue. Why people would want to conflate this important idiom with the equally important and unrelated idiom of state sharing is a mystery to me, as they work just as well together or separately. What's the contrary of "divide and conquer" -- "conflate and suffer"?-)

andy mckay 14 years, 9 months ago  # | flag

Double comments. Sorry there was a bug, its fixed now.

Vadim Nasardinov 13 years, 10 months ago  # | flag

what about GC? Philosophical considerations aside, the "classic" Singleton pattern would seem to perform better than the Borg pattern, when it comes to garbage collection, wouldn't it? What is the point of having the garbage collector keep track of reference counts for a million objects, when one object would suffice?

Oren Tirosh 13 years, 10 months ago  # | flag

Singletons using new-style classes.

class Singleton(object):
    def __new__(type):
        if not '_the_instance' in type.__dict__:
            type._the_instance = object.__new__(type)
        return type._the_instance

Just inherit from this class. Everything else is handled automatically.

Alex Naanou 13 years, 4 months ago  # | flag

New-style Borg...

# here is the new-style Borg (not much more complex then the "old-style")
class Borg(object):
    _state = {}
    def __new__(cls, *p, **k):
        self = object.__new__(cls, *p, **k)
        self.__dict__ = cls._state
        return self
Jeff Pitman 10 years, 10 months ago  # | flag

Re: New-style Borg... For those just joining us from Google, use Oren Tirosh's in the comment one above. Two instances of this singleton do not pass the id(a) == id(b) test. Oren's does.

Jeff Pitman 10 years, 10 months ago  # | flag

Slight improvement.

class Singleton(object):
    def __new__(cls, *p, **k):
        if not '_the_instance' in cls.__dict__:
            cls._the_instance = object.__new__(cls)
        return cls._the_instance

Type is now a keyword. And classes can be initialized with params. This handles that.

Luke Plant 10 years, 8 months ago  # | flag

classes and modules are singletons. You don't need singletons in python simply because classes and modules are always singletons, and they are also first class objects. They can have everything instances have, and as import statements don't make copies there is only ever one of them. We don't need no stinkin' design patterns.

Andre Pfeuffer 10 years, 6 months ago  # | flag

Classes and modules are singeltons, but who prevents us? I agree, but who prevents us from doing stupid things then? Such as instanciating a class, meant to be a singelton within a modul twice?

gissehel-aspn 10 years, 5 months ago  # | flag

Classes and modules are singeltons, but who prevents us? : You ! Let's suppose you're implementing a singleton-like class, and you create an instance in your module. You don't want anyone else to be able to create another instance of your class. Just remove the class just after having created your instance ! That's all...

Exemple (in module singleton) :

class MySingleton( object ) : pass

singleton = MySingleton() MySingleton = None

Then, you can use : from singleton import singleton

But you can't do : import singleton singleton.MySingleton()

Of course, you can acces to the class threw the instance. But if you're lurking within the instances to find funny things, you'll have problems everywhere...

Alexey Borzenkov 9 years, 1 month ago  # | flag

You forgot about type. Who can prevent someone from doing type(singleton)(...)?

I think the real solution could be class with classmethods and __new__ raising an Error, then you don't need no instance. But even then someone could have just replaced __new__. :)

chema quinn 8 years, 11 months ago  # | flag

simple... If using a class as a singleton, you need http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52304 static methods. You can easily write your __init__ funtion to raise an error.

Alex Naanou 8 years, 7 months ago  # | flag

Singleton is not Borg! :). Oren's approach is Singleton and I implemented a Borg, there is one fundamental difference: Borg are different objects with shared state and Singleton are One object... this may come useful, in more complex examples, a Borg, for instance, can have partial private namespaces, that is, a namespace that is part private (stored in a particular instance) and part shared, this is harder and less intuitive to do with a Singleton pattern.

fxiii 5 years, 6 months ago  # | flag

SemiBorg. What about:

class SemiBorg:
    __super_shared_state = {}
    def __init__(self, key="default"):
        self.__dict__ = self.__super_shared_state.setDefault(key, {})
Max Egger 3 years, 11 months ago  # | flag

How about a class decorator? Something along the lines of:

def borg(cls):
    cls._state = {}
    orig_init = cls.__init__
    def new_init(self, *args, **kwargs):
        self.__dict__ = cls._state
        orig_init(self, *args, **kwargs)
    cls.__init__ = new_init
    return cls

Allows you to write this:

@borg
class Foo(object):
    def say_hello(self):
        print "hello, I'm a borg"
Bill Hallahan 3 years, 3 months ago  # | flag

This is a nice pattern, but the implication by the author that this pattern is always better than the Singleton pattern is not correct.

As noted already, the Singleton pattern allows for only one instance of the class, whereas this pattern allows many instances with shared state. Often, only a single instance of a class is desired because of memory, particularly in languages without built-in garbage collection, although even in Python, it wouldn't typically make sense to have a million objects when only one Singleton is needed.

All patterns have advantages and disadvantages.

Alex Martelli (author) asked: "What happens in a large system when two separate subsystems both inherit from (extend) a singleton-class? It's anything but clear to me -- error at runtime, at compiletime, at linktime (none such in Python, let's say at import-time), or what behavior...?"

In some languages, such as C++, Singletons are often implemented with a template class. One would never inherit from this class, instead, one would inherit from the class instantiated in the template and create another singleton using the template with that new class.

Of course, once using a singleton, changing to multiple instances is problematic, which is why their use should be sparse - however, they do solve a memory problem that the Monostate (Borg) pattern does not solve.

Add a comment

Sign in to comment

Created by Alex Martelli on Fri, 17 Aug 2001 (PSF)
Python recipes (4483)
Alex Martelli's recipes (27)
HongxuChen's Fav (39)
python sets (2)
Favorites (1)

Required Modules

  • (none specified)

Other Information and Tasks