singleton problems

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Sun Oct 3 06:02:39 EDT 2010


On Sun, 03 Oct 2010 01:55:00 -0700, harryos wrote:

> hi
> I have been trying out singleton design pattern implementations..I wrote
> this,
> 
> 
> class Singleton(object):
>     _instance = None
>     def __new__(self, *args, **kwargs):
>         if not self._instance:
>             self._instance = super(Singleton, self).__new__(self,
> *args, **kwargs)
>         return self._instance

Since __new__ is called before the instance exists, it doesn't receive an 
instance as the first argument. Instead it receives the class. While you 
can call the parameter anything you like, it is conventional to call it 
cls rather than self.


> class Mysingle(Singleton):
>     def __init__(self,name):
>         self.name=name
> 
> if __name__=='__main__':
>     s1=Mysingle('john')
>     s2=Mysingle('jim')
>     s3=Mysingle('jeff')
>     print 's1=',s1,s1.name
>     print 's2=',s2,s2.name
>     print 's3=',s3,s3.name
> 
> This is the result I got
> s1= <__main__.Mysingle object at 0xb776492c> jeff 
> s2= <__main__.Mysingle object at 0xb776492c> jeff 
> s3= <__main__.Mysingle object at 0xb776492c> jeff 
> /home/dev/eclipse_workspace/pylearn/src/designpatterns.py:11:
> DeprecationWarning: object.__new__() takes no parameters
>   self._instance = super(Singleton, self).__new__(self, *args,
> **kwargs)
> 
> shouldn't the name of s1,s2,s3 be 'john' instead of 'jeff'? 

No. When you create the instance, it is indeed called 'john'. But then 
you call __init__ two more times, you modify it to 'jim' and then 'jeff'.


> Also,how do I correct the deprecation problem?

By not passing any arguments to object.__new__.

Try this instead:

class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, self).__new__(cls)
            # or if you prefer: object.__new__(cls)
        return cls._instance

class Mysingle(Singleton):
    def __init__(self, name=None):
        if hasattr(self, name):
            if name is not None:
                raise ValueError(
                "cannot give name if instance already exists")
        else:
            if name is None:
                raise ValueError("name is not given")
            self.name = name

Or you could choose to just ignore the name if the instance already 
exists:

class Mysingle(Singleton):
    def __init__(self, name):
        if not hasattr(self, name):
            self.name = name



> Can somebody comment?


Yes. The singleton design pattern is over-rated and frequently 
unnecessary. Many people consider it to be an anti-pattern far more often 
than it is a pattern -- often people needlessly insist on making classes 
singletons when they shouldn't be.

If you do need a singleton, the simplest way in Python is just to use a 
module. You initialise the singleton with:

import module

You can do this as many times as you want. Then you call functions on it 
with:

module.function(args)

You need, literally, zero extra coding.

Another alternative is to realise that the singleton pattern's focus on 
object *identity* is unnecessary if all you want is shared state:

http://code.activestate.com/recipes/66531/


-- 
Steven



More information about the Python-list mailing list