This singleton pattern implementation was working as expected, but there is a situation unexpected (see Test). What would have been wrong?
Code:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(
cls, *args, **kwargs)
print("new class created")
return cls._instance
class CounterClassBase(object):
def __init__(self, *args, **kwargs):
super(CounterClassBase, self).__init__(*args, **kwargs)
print("Counter class init in base")
class Counter(CounterClassBase, Singleton):
counter = None
def __init__(self, *args, **kwargs):
super(Counter, self).__init__(*args, **kwargs)
print("Counter class init")
self.counter = 0
import pdb
pdb.set_trace()
Test:
(Pdb) var1 = Counter()
new class created
Counter class init in base
Counter class init
(Pdb) var2 = Counter()
Counter class init in base
Counter class init
(Pdb) var3 = Counter()
Counter class init in base
Counter class init
(Pdb) var1.counter = 3
(Pdb) var1.counter
3
(Pdb) var2.counter
3
(Pdb) var3.counter
3
(Pdb) var4 = Counter()
Counter class init in base
Counter class init
(Pdb) var4.counter
0
(Pdb)
Expected value for var4.counter
was 3, not 0.
Edit:
As mentioned in the answers, my test was wrong. There is seen obviously that the "Counter class init" statement is printed, so init() is called, so variables are initialized everytime a new class instance is created.
So I changed my code as follows (source: https://stackoverflow.com/a/8665179/1952991) :
class Singleton(type):
def __init__(self, *args, **kwargs):
super(Singleton, self).__init__(*args, **kwargs)
self.__instance = None
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super(Singleton, self).__call__(*args, **kwargs)
return self.__instance
class Counter(object):
__metaclass__ = Singleton
counter = None
def __init__(self, *args, **kwargs):
print("Counter class init")
self.counter = 0