singleton problems

Arnaud Delobelle arnodel at gmail.com
Sun Oct 3 06:54:22 EDT 2010


harryos <oswald.harry at gmail.com> writes:

> 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
>
>
> 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'?
> Also,how do I correct the deprecation problem?Can somebody comment?

That's because overriding __new__ doesn't prevent __init__ from being
executed.  The reason for this is that when you do:

    MySingle('jeff')

what is executed is:

    MySingle.__metaclass__.__call__('jeff')

And as by default, MySingle.__metaclass__ is type (I mean the type
called 'type'), its __call__ method is called.  This method calls first
the MySingle.__new__ and then MySingle.__init__ on the result.  So you
need to override type.__call__.  Here is a very simple implementation to
show you the principle (assuming Python 2.X):


class MetaS(type):
    def __call__(self, *args, **kwargs):
        # Here, self is the class to be instanciated
        instance = getattr(self, "_instance", None)
        if instance is None:
            instance = super(MetaS, self).__call__(*args, **kwargs)
            self._instance = instance
        return instance

class Singleton(object):
    __metaclass__ = MetaS

class MySingle(Singleton):
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return str(self.name)


Now let's see this in action:

>>> a = MySingle("John")
>>> b = MySingle("Jeff")
>>> a is b
True
>>> a.name
'John'
>>> b.name
'John'

HTH

PS: OTOH, singletons are rarely of use in Python as one can use
module-level instances instead.

-- 
Arnaud



More information about the Python-list mailing list