My python version:
python3 --version
Python 3.9.2
Issue 1:
What does isinstance
function mean?
class Singleton1(object):
__instance = None
def __init__(self):
if not hasattr(Singleton1, '__instance'):
print("__init__ method called, but no instance created")
else:
print("instance already created:", self.__instance)
@classmethod
def get_instance(cls):
if not cls.__instance:
cls.__instance = Singleton1()
return cls.__instance
Initialize it :
x = Singleton1()
__init__ method called, but no instance created
Have a check with isinstance
function:
isinstance(x,Singleton1)
True
If x is not an instance,why does isinstance(x,Singleton1)
say it is an instance of Singleton1?
Issue2:
Why __init__
method can't be called anyway?
Now repalce all __instance
(double underscores) with _instance
(single underscore) in the class Singleton1
and replace all Singleton1
with Singleton2
:
class Singleton2(object):
_instance = None
def __init__(self):
if not hasattr(Singleton2, '_instance'):
print("__init__ method called, but no instance created")
else:
print("instance already created:", self._instance)
@classmethod
def get_instance(cls):
if not cls._instance:
cls._instance = Singleton2()
return cls._instance
Initialize it:
y = Singleton2()
instance already created: None
Why __init__
method can't be called anyway in this status?
snakecharmerb 31.7k1010 gold badges5656 silver badges9696 bronze badges
How about the first question? –
showkey
15 hours ago
@snakecharmerb on issue1,Why someone say it is lazy instantiation ,if isinstance(x,Singleton1) is true,it is no need to call with Singleton1.get_instance() ,because the instance is already created during instantiation.
CodePudding user response:
The hasattr
check does not do what you think it does. Using Singleton2
*, hasattr(Singleton2, '_instance')
is always True
, because the class has an attribute named _instance
. You want to check the value of the instance, so use getattr instead; then the expected output will be printed.
The isinstance
checks succeed because Singleton2()
will return a new instance each time - there is nothing to prevent this. You can add a __new__
method to create _instance
and return it every time Singleton2()
is called. Note that this will mean that _instance
will always exist by the time __init__
is called.
class Singleton2:
_instance = None
def __new__(cls):
if cls._instance is not None:
return cls._instance
instance = super().__new__(cls)
cls._instance = instance
return instance
* The hasattr
check in Singleton1
is complicated by the name-mangling performed on __instance
. In general, avoid using double-underscored variable names, except for avoiding name clashes in class hierarchies.