Why do these two statement give different outcomes...
print(Database().id == Database().id)
(which gives False)- but it gives True this way
d1 = Database()
d2 = Database()
print(d1.id == d2.id)
here's the entire code:
import random
class Database:
initialized = False
def __init__(self):
self.id = random.randint(1, 101)
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Database, cls).__new__(cls, *args, **kwargs)
return cls._instance
print(Database().id == Database().id)
# False
d1 = Database()
d2 = Database()
print(d1.id == d2.id)
# True
CodePudding user response:
__new__()
always calls __init__()
if the returned instance is of the correct class. This means, every Database()
call is still going through and setting a new random value to id
.
This id
is an instance variable that you have defined, it will not really affect the result of id()
, which is why if you do
print(Database() is Database())
it will return True
even though the id
check returned false. The instance is the same, you just changed id
value in between, so they evaluate as False
.
In the second case, because the instance is the same, both of them get the value generated by __init__()
when you assign d2
. You can confirm this by adding a print(d1.id)
before and after d2
is assigned.
You need to make use of the initialized
boolean to correctly skip the code in __init__()
import random
class Database:
initialized = False
def __init__(self):
if not self.initialized:
self.id = random.randint(1, 101)
self.initialized = True
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Database, cls).__new__(cls, *args, **kwargs)
return cls._instance
Take a look at issue with singleton python call two times __init__ if you want to see other implementations of a singleton class or alternative approaches that avoid singleton entirely.