[Tutor] singleton pattern

Michael P. Reilly arcege@speakeasy.net
Fri, 18 May 2001 12:14:11 -0400 (EDT)


alan.gauld@bt.com wrote
> 
> Acerge wrote:
> > class SingletonInstance:
> >   instance = None  # class member for the singleton instance
> >   def __init__(self, klass):
> >     if self.__class__.instance is None:
> 
> OK, I've now read the docs and had a play.
> 
> This is solving a slightly different problem, I think.
> The self.__class__.instance is only a convoluted way of writing
> SingletonInstance.instance - I think the latter is clearer.

Except that self.__class__.instance works with subclasses of
SingletonInstance but SingletonInstance.instance does not.  The class I
gave was geared more to subclasses for the individual singleton classes
(which addressed your different class issue below).  But since I had
already specified that there had been lengthy discussions in more
appropriate forums, I wasn't going to go further.

> >       self.__class__.instance = klass() # make the instance
> 
> This is setting the instance attribute of the SingletonInstance
> class to an instance of the manufactured class. I'm not sure how 
> this gives us a singleton structure? It will ensure that 
> calls to SingletonInstance produce a new instance of klass
> and assign it to the class variable, but for a singleton we 
> want to ensure that calls to the constructor return a pointer 
> to *the same* instance.

Pointing to the same instance is not a necessary condition for the
the problem of a singleton class.  It might be how you think it should
work, but nothing in the functionality defined even hints to "Class()
is Class()" as a tautology.

The above does not "ensure that calls to SingletonInstance produce a new
instance of klass".  It ensures that SingletonInstance instances will
always reference ONE instance (created by SingletonInstance) of klass.

With:
>>> aspam = SingletonInstance(Spam)
>>> bspam = SingletonInstance(Spam)
>>> aspam.__class__.instance is bspam.__class__.instance
1
>>> 

I assert that for any two instances of a call to the SingletonInstance
class, the 'instance' class member will always be the first instance
of the klass given in the first call and that the two instances behave
identically.

The goal, and requirement, of a singleton class is that an instance
from a class _behaves identically_ to any other instance of that class,
not that only one instance can be created.  In Python, there is no
way for a Python class constructor to return anything other than a new
instance.  For that you might want to create the factory and use __call__.
This solution allows for any instance to always access the data in the
first instance created.  Other more involved solutions would be to always
use the class members, never instance members.  The point is that object
identity is not a condition of singleton classes.

> Thus:
> foo = SingletonInstance(MyFileClass)
> 
> and
> 
> bar = SingletonInstance(MySocketClass)
> 
> should make foo and bar reference the same instance (but, 
> in this case,  set the internal instance variable 
> to a new class reference)
[Here, functionally, I would hope that MyFileClass would want a
different singleton instance than MySocketClass since they are different
classes, but it was also mentioned above that here there should be two
subclasses of SingletonInstance to solve that.]

Commonly idioms to this have already been put out, and ppl just need
to look at the multitude of modules in the standard library that
implement them.  Mine was not the answer to the original question and
I didn't attempt to make it such, but more of a method of dealing with
overly-complicated, abortive method at instance creation.

  -Arcege

-- 
+----------------------------------+-----------------------------------+
| Michael P. Reilly                | arcege@speakeasy.net              |