Few years ago I found an implementation of the Singleton pattern in Python by Duncan Booth:
class Singleton(object):
\"\"\"
Singleton class by Duncan Boo
You need to drop any additional arguments you are passing when you construct the object. Change the offending line to:
cls._instance = object.__new__(cls)
or
cls._instance = super(Singleton, cls).__new__(cls)
though I think you'll be fine with the first (diamond inheritance and singletons sound as though they shouldn't be mixed).
P.S. I did try this suggestion and it works for me so I don't know why it didn't work for you.
Edit in response to @dragonx's comment: As pointed out in the comments, object.__new__
will throw an exception if you pass on *args, **kwargs
so the super call to __new__
should not include any arguments apart from cls
. This wasn't the case when the original article was written. Also of course if you choose to base your singleton on some other type such as a tuple
you would then need to pass the appropriate arguments.
I found this pattern described in a Python 3 pattern and idioms source. This should certainly help. I would love to know if it solves your problem, although it may violate the minimal impact condition in your question.
Python 3: The Singleton
So based on the answers from @Sven and @Duncan I found a solution which works for me. The problem actually wasn't in the line of the code raising the TypeError, but in the signature of the __new__()
method. The call of the object.__new__(cls)
shall be without the *args, **kwargs, but they have to remain in the Singleton.__new__()
definition. This is the modified Singleton:
class Singleton(object):
"""
Singleton class by Duncan Booth.
Multiple object variables refers to the same object.
http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html
"""
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
And this is an example of sub-classing (which was the issue):
class Child(Singleton):
def __init__(self,param=None):
print param
print 'Doing another stuff'
ch=Child('Some stuff')
I still don't understand why the signature of Child's __init__()
has to match to Singleton's `new(), but this solution works.