Reputation: 581
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.
Upvotes: 0
Views: 632
Reputation: 96028
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.
Upvotes: 1