0

I want to make a python singleton class and so that the instance of that class is exactly the same when everywhere else in the code calls the class after the program is on.

I tried to find singleton example and found one from link: https://wikidocs.net/3693

class Singleton(object):
    _instance = None
    def __new__(class_, *args, **kwargs):
        if not isinstance(class_._instance, class_):
            class_._instance = object.__new__(class_, *args, **kwargs)
        return class_._instance

and then testing like this

class Test(Singleton):
    def __init__(self, name=None):
        print(name)

test1 = Test('a')

expecting to show name that is given when it is initialized but this gives me an error

TypeError                                 Traceback (most recent call last)
<ipython-input-55-f3383e846037> in <module>()
----> 1 test1 = Test('a')

<ipython-input-33-222ac7a13884> in __new__(class_, *args, **kwargs)
     27     def __new__(class_, *args, **kwargs):
     28         if not isinstance(class_._instance, class_):
---> 29             class_._instance = object.__new__(class_, *args, **kwargs)
     30         return class_._instance

TypeError: object() takes no parameters

But when I try this, this one success

Test() # with no prarameter
test1 = Test('a') # this prints 'a' without error

I would like to know how to fix this. Otherwise, I have to initialize without parameters at the beginning when I start the program.

The reason I want to get the parameter is that when the parameter is changed at some point then I want to apply the changed information to everywhere that calls this class.

2
  • I'm assuming SingletonInstance2 is just Singleton? Commented Oct 7, 2020 at 2:39
  • I was testing many cases .. and made a mistake when I posted. You are correct. Commented Oct 7, 2020 at 2:41

1 Answer 1

1

The singleton pattern is pretty pointless in Python. Almost always, you are just better off using a module. Or some factory function as your main construction API, e.g. getLogger.

If you really insist on making your class superficially a singleton (this can always be subverted), i'd suggest the metaclass approach because it side-steps all sorts of complications of overriding __new__, although, metaclasses introduce their own complications.

But to address your question, this code is outdated, passing arguments to object.__new__ will now throw an error instead of being simply ignored. To make this work, simply do not pass any arguments to __new__:

In [1]: class Singleton(object):
   ...:     _instance = None
   ...:     def __new__(class_, *args, **kwargs):
   ...:         if not isinstance(class_._instance, class_):
   ...:             class_._instance = object.__new__(class_)
   ...:         return class_._instance
   ...:

In [2]: class Test(Singleton):
   ...:     def __init__(self, name=None):
   ...:         print(name)
   ...:
   ...: test1 = Test('a')
a

Note, __init__ will be called each time you "instantiate" your singleton:

In [3]: test2 = Test('b')
b

In [4]: test1 is test2
Out[4]: True

Which may or may not be desirable.

But seriously reconsider if you need a singleton classes. Even in languages where they sort of make sense, e.g. Java, they are often an anti-pattern, and are merely a way to hide mutable global state in an OOP-encapsulated façade. Which again, brings me to the original suggestion of just using a module, then you have no pretense.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for your considerable thoughts and answer, but I mentioned at the beginning I want this class to be used in everywhere in the program exactly same. If any change of attribute is occurred then I want it to be uniformly used in else where as well. That is the purpose of using singleton...
Your answer works as exactly I wanted it to be. Thank you again
@IsaacSim right, exactly that's my point, you want to use mutable, global state. You could just use a module. But if this is what you are looking I'm glad you've solved your issue

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.