singletons

C

Craig Allen

Hey, forgive me for just diving in, but I have a question I was
thinking of asking on another list but it really is a general question
so let me ask it here. It's about how to approach making singletons.
Background: I've been programming in python seriously for about a year
now, maybe a little longer depending how you count, and the system I
am making is sophisticated enough that I've had to enter into a few
idioms which were beyond my knowledge of python, and I had to do quick
research and test my ideas with test code (which of course can miss
subtle problems). Otoh, I have decades of programming experience now
and wasn't totally without footing. I think I have a solution I like
for creating something to act as a singleton but I'm curious what
other's think.

I have several classes in our system which need to act like
singletons, they are libraries of data classifications, and other such
libraries of configurations for the system which need to be global.

The first thing I found searching for singleton, early in this
project, trying to be a good citizen and find a decent idiom from the
python community itself, knowing someone had mentioned "singleton" and
"python" together at some point, was a recommendation to do this:

(option 1)

class TehLibrary(object):
__single = None
def __init__(self):
if (TehLibrary.__single):
raise AlreadyExistsException # or whatever

This sucks because that means creation of the object has to be in a
try block as a matter of course, something I promptly hid in a factory
function, but still.

But the way this worked made me realize that the Class itself is a
full fledged object, quite instance-like from my C++ addled (I love
you C++) perspective and it's single. If I can store that instance, I
can make a class that shares member at the class level. The class
doesn't even have to be a singleton exactly.

(option 2)
Therefore option two is a family of options where class level members
can be used to share whatever needs to be shared, though strictly the
class is not a singleton since multiple instances are created which
merely share the data that should be single (say a big dictionary of
configuration information the class manages).

(option 3)
I still wanted actual singletons and realized that since I had to
create a factory function even in option 1, that I could use module
level variables to control the behavior of those factories, which led
me to realize I'm basically just using the module itself as a
singleton. And this is sort of where I have arrived... when I import
the modules it runs code to build up it's basic services, much like an
object construction. It only runs once no matter how many times it's
imported. When client code asks for the library that should be a
singleton, it gets a singleton which has been stored in a module level
variable.

Anyone have any comments? Is there anything wrong, evil, or ugly
about using a module this way, or am I correct to think that actually,
this is a common approach in python.

Is it pythonic?
 
C

castironpi

Hey, forgive me for just diving in, but I have a question I was
thinking of asking on another list but it really is a general question
so let me ask it here.  It's about how to approach making singletons.
Background: I've been programming in python seriously for about a year
now, maybe a little longer depending how you count, and the system I
am making is sophisticated enough that I've had to enter into a few
idioms which were beyond my knowledge of python, and I had to do quick
research and test my ideas with test code (which of course can miss
subtle problems).  Otoh, I have decades of programming experience now
and wasn't totally without footing.  I think I have a solution I like
for creating something to act as a singleton but I'm curious what
other's think.

I have several classes in our system which need to act like
singletons, they are libraries of data classifications, and other such
libraries of configurations for the system which need to be global.

The first thing I found searching for singleton, early in this
project, trying to be a good citizen and find a decent idiom from the
python community itself, knowing someone had mentioned "singleton" and
"python" together at some point, was a recommendation to do this:

(option 1)

class TehLibrary(object):
   __single = None
   def __init__(self):
      if (TehLibrary.__single):
         raise AlreadyExistsException # or whatever

This sucks because that means creation of the object has to be in a
try block as a matter of course, something I promptly hid in a factory
function, but still.

But the way this worked made me realize that the Class itself is a
full fledged object, quite instance-like from my C++ addled (I love
you C++) perspective and it's single.  If I can store that instance, I
can make a class that shares member at the class level. The class
doesn't even have to be a singleton exactly.

(option 2)
Therefore option two is a family of options where class level members
can be used to share whatever needs to be shared, though strictly the
class is not a singleton since multiple instances are created which
merely share the data that should be single (say a big dictionary of
configuration information the class manages).

(option 3)
I still wanted actual singletons and realized that since I had to
create a factory function even in option 1, that I could use module
level variables to control the behavior of those factories, which led
me to realize I'm basically just using the module itself as a
singleton. And this is sort of where I have arrived... when I import
the modules it runs code to build up it's basic services, much like an
object construction.  It only runs once no matter how many times it's
imported. When client code asks for the library that should be a
singleton, it gets a singleton which has been stored in a module level
variable.

Anyone have any comments?  Is there anything wrong, evil, or ugly
about using a module this way, or am I correct to think that actually,
this is a common approach in python.

Is it pythonic?

In option 1, you could use the __new__ method, and return the existing
instance if there is one, or, I believe, call __init__ on the
superclass. Alternatively, define your own 'create' method with the
@classmethod decorator, instantiate with ClassA.create( ), and return
any existing instance from there. The catch is you need to rely on
the discipline of not using the default instantiation syntax.

In option 2, you would have to wrap the functions with the
@staticmethod decorator, and all instance methods would act on the
same object.

Each of these have different consequences for inheritance, if that is
on the horizon in your project.
 
C

Craig Allen

I don't intend to do much subclassing of this, but of course, I'd
rather not second guess the future and it's not hard to imagine we
will come to some point that we need to do just that. Thanks for the
ideas about repairing option one, which I'd given up, though the ideal
is still that

tl = TehLibrary() would always return the same object.

-craig
 
A

Asun Friere

Is it pythonic?

You probably can't get anymore pythonic than something written by the
BDFL. In describing the use of __new__ in <i>Unifying types and
classes in Python 2.2</i> he gives this recipe for a Singleton.


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

You might find this a useful starting point.
 
L

Lawrence D'Oliveiro

In message
... the ideal is still that

tl = TehLibrary() would always return the same object.
.... @classmethod
.... def __new__(self, cls) :
.... return self
True
 
C

Carl Banks

Anyone have any comments?  Is there anything wrong, evil, or ugly
about using a module this way, or am I correct to think that actually,
this is a common approach in python.

Is it pythonic?


The one drawback to this is that it could require lots of globals
definitions. Whereas in a regular class you could do this:

def something(self):
self.var = 1
self.max = 10

using a module as a singleton you'd be doing this:

def something():
global var
global max
var = 1
max = 10


If you have a lot of "attributes" of your module to redefine, I'd
suggest taking steps to avoid globals. The most straightforward way
is to define a self variable in your module that is bound to the
module itself, and access all "attributes" through that. The
following code should suffice (though it may not work in some corner
cases):

self = sys.modules[__name__]

So then you could rewrite the something method like so:

def something():
self.var = 1
self.max = 10


[Another possibility, and this is what I do, is to use a function
decorator that passes the module in as the first argument. I have
reasons for doing it but it doesn't do anything the above method
does. It would be used like this:

@modmethod
def something(self):
self.var = 1
self.max = 10

]


Carl Banks
 
U

Uwe Schmitt

I have several classes in our system which need to act like
singletons, they are libraries of data classifications, and other such
libraries of configurations for the system which need to be global.
...

Is it pythonic?

My approach in this situation is to use the Borg pattern instead
of singeltons. This is really pythonic, very simple and usefull.

Look at http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531
The german wikipedia shows another solution using metaclasse:
http://de.wikipedia.org/wiki/Singleton_(Entwurfsmuster)#Das_Borg-Pattern

Greetings, Uwe
 
C

Craig Allen

My approach in this situation is to use the Borg pattern instead
of singeltons. This is really pythonic, very simple and usefull.

Look athttp://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531
The german wikipedia shows another solution using metaclasse:http://de.wikipedia.org/wiki/Singleton_(Entwurfsmuster)#Das_Borg-Pattern

Greetings, Uwe

thanks uwe, doing some searching I ran into the borg pattern this
morning. Definitely relevant.

Thanks again and all for the feedback, I feel much reassured about the
options when this sort of thing is required.
 
L

Lawrence D'Oliveiro

In message
That's great, I simply didn't find that when looking. Thanks!

Also note that

s == TehLibrary

will be true (the instance equals the class). I assume that doesn't matter
for your purposes. :)
 
P

Paddy

Hey, forgive me for just diving in, but I have a question I was
thinking of asking on another list but it really is a general question
so let me ask it here.  It's about how to approach making singletons.

Hi Craig,
This might be good for a general background on Design Patters in
Python:


- Paddy.
 
A

Aahz

(option 2)
Therefore option two is a family of options where class level members
can be used to share whatever needs to be shared, though strictly the
class is not a singleton since multiple instances are created which
merely share the data that should be single (say a big dictionary of
configuration information the class manages).

That's only true if you actually instantiate the class. You can just
use the class directly -- that's what I do.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top