5

I have a class that has the standard python singleton form I use. It also inits a single value, but rather than init it in each instance, I init it in __new__() when I do the singleton handling. Is this the pythonic way to do it? If not, how else can I?

class Foo(object):
    _inst = None
    def __new__(cls, val):
        if Foo._inst is None:
            Foo._inst = super(Foo, self).__new__(cls)
            Foo._inst.val = val
        return Foo._inst

This is obviously the simplified form. I have used the construction of waiting till __init__() to check and set Foo._inst to handle run once init for a singleton, but that seems ripe for synchronization errors in a multithreaded situation. For situations where there're no values that can get corrupted in the existing instance if __init__() is run again, there's no harm in putting the init in __init__(), except that you are running code that effectively does nothing when you don't need to, but there are often corruptible state values I don't want to overwrite. I know singletons are evil too, but some times, they are the best solution (like defining special use types I want to be able to check with is).

This seems like the best solution I can come up with, but I feel dirty initializing instance values in __new__(). Does anyone have ideas on how to handle this better?

Silas Ray
  • 25,682
  • 5
  • 48
  • 63
  • 7
    It is an original sin to use singletons. They are a way to add additional drawbacks and weird restrictions to globals. If you need global state, use globals, but better try to avoid them. Never use singletons. – Sven Marnach Mar 02 '12 at 17:25
  • 1
    @Sven Marnach I do what I can to avoid singletons and globals of course, but there are instances where they are the best solution. For instance, I just implemented a Ternary class, but I don't need more than one instance of each type (True, False, Unknown), and actually, having only one of each lets me use it more like a bool by allowing the `is` operator to work. So while singletons are to be avoided, there should be good ways to use them when they are the best choice. – Silas Ray Mar 02 '12 at 17:29
  • 3
    Don't you mean "cardinal sin"? – Nick Vaccaro Mar 02 '12 at 17:29
  • 5
    Use a Borg. (It looks like a normal class but the instance dictionary is stored on the class, so every instance actually acts the same.) – Katriel Mar 02 '12 at 17:30
  • Also you shouldn't be using `is` on boolean values. For example, `[] is not False` but the empty list is boolean false. – Katriel Mar 02 '12 at 17:31
  • @katielalex that's what I'm really doing in my real code, but for simplicity, I only wrote the code that illustrates the question I have here. Yes, they all evaluate to False with bool(), but sometimes you do actually want to know the difference. – Silas Ray Mar 02 '12 at 17:31
  • @katrielalex, +1 for amusingly named pattern and concise description. :-) – alexis Mar 02 '12 at 17:35
  • @SvenMarnach I don't have `__init__` in my code... – Silas Ray Mar 02 '12 at 17:57
  • @Norla I'm a programmer, not a theologian. ;) – Silas Ray Mar 02 '12 at 17:58
  • This question seems related to [this answer](http://stackoverflow.com/a/9504358/1132524) *(at the end* kindall *mentions the `is` comparison)* – Rik Poggi Mar 02 '12 at 18:04
  • @SvenMarnach oh that, yeah, thanks. Missed that... edited. – Silas Ray Mar 02 '12 at 18:27
  • @ Rik Poggi yes, it is related, only because after being on that thread I had a use for such a thing in my code as well. However, the general case of doing initialization in __new__() is more general, as are the problems I discuss in this thread. – Silas Ray Mar 02 '12 at 18:29

3 Answers3

4

You can always use global variables instead of singletons. Example for a class with three different instances:

class _Ternary(object):
    """Internal class.  Don't instantiate!"""
    def __init__(self, value):
        self.value = value

ternary_0 = _Ternary(0)
ternary_1 = _Ternary(1)
ternary_2 = _Ternary(2)

def ternary(value):
    """Factory function to request a "ternary" instance."""
    return {0: ternary_0, 1: ternary_1: 2: ternary_2}[value]

This is straight-forward and will avoid the pain of singletons.

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • But with this pattern how do you make operator-overloading work nicely? For example, how would you make `ternary_1 - ternary_1` return `ternary_0`? – GrantJ Jun 05 '15 at 18:09
  • @GrantJ: I don't understand the problem. Define a `__sub__` method on the `Ternary` class? – Sven Marnach Jun 06 '15 at 10:06
2

To answer the first question: Singletons are not used too often in Python as they are not really required.

To answer the second: If you think you really need them, there is slightly cleaner, similiar pattern called "Borg" which is sometimes used, see: the Borg design pattern If you need to just share some attributes between instances and don't need full-blown singleton (which can be instantiated once) you may simply use class attributes like so:

class Foo( object ):
    val = ...

    def __init__( self ):
        ...

Then all instances will share the same value of the "val" attribute.

kgr
  • 9,750
  • 2
  • 38
  • 43
  • I may have oversimplified my example... in the more common example, I actually have an instance dictionary stored in the class, and my goal is to limit the number of special type instances. So you end up with `Foo._insts = {1 : Foo(1), 2 : Foo(2), 3 : Foo(3)}`. Then you end up with a unique type for the 3 values, but only one instance per value. – Silas Ray Mar 02 '12 at 17:39
  • Python is not a language which allows for anything so strict, i.e. you probably won't be able to protect yourself 100% anyway. However if you just want to make a decent interface for that, why not make two classes, one of which is a register and allows for creating instances of other if the limit hasn't been exceeded ? i.e. Foo() and FooRegistry() and have a method FooRegistry.create() which returns Foo instance if the limit has not been exceeded or raises an exception otherwise or does somethig else to handle the situation... ? – kgr Mar 02 '12 at 17:43
  • Why add another layer of classes to do the same thing? This collapses FooRegistery and Foo in to a single class where FooRegistery.create() turns in to Foo.__new__(). – Silas Ray Mar 02 '12 at 17:47
  • Because we decided that it's not too elegant and pythonic, see @Sven Marnach comment to your question. Also the classes should map to some kind of logical objects from your problem domain. With what you said you clearly have two objects here - Foo, and some kind of a registry which keeps track of Foos, so why not make it simple (KISS principle) and clean ? – kgr Mar 02 '12 at 17:51
  • Of course, I'm not trying to attack you, I'm just proposing alternative way :) – kgr Mar 02 '12 at 17:52
  • If you want to get pedantic, you have 2 objects already, the object of type type that is Foo, and the object that is an instance of Foo... ;) – Silas Ray Mar 02 '12 at 17:54
  • I'm usually not that pedantic :) – kgr Mar 02 '12 at 17:57
  • 2
    @sr2222: If you think your example is oversemplified you can [edit](http://stackoverflow.com/posts/9537617/edit) your quesion and update it/improve it/add more useful information. State there your requirements, and your actual code, this way we'll be really able help you/tell you if there's something wrong. – Rik Poggi Mar 02 '12 at 17:58
1

There's no better way to create singletons. If you're going for it (and three-valued logic is about the only example I can think of where this makes sense), then you can do it the way you are.

Marcin
  • 48,559
  • 18
  • 128
  • 201
  • Yep, that was my use case for the [Python Tribool](http://www.grantjenks.com/docs/tribool/) data type. – GrantJ Jun 05 '15 at 18:05