Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it an 'original sin' to do init work in __new__? If so, how best to handle run once init for singletons?

Tags:

python

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?

like image 809
Silas Ray Avatar asked Mar 02 '12 17:03

Silas Ray


1 Answers

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.

like image 102
Sven Marnach Avatar answered Oct 30 '22 03:10

Sven Marnach