1

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 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.

showkey
  • 482
  • 42
  • 140
  • 295
  • may help https://stackoverflow.com/questions/1301346/what-is-the-meaning-of-single-and-double-underscore-before-an-object-name – emptyhua Oct 20 '21 at 14:07

1 Answers1

1

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.

snakecharmerb
  • 47,570
  • 11
  • 100
  • 153
  • How about the first question? – showkey Oct 21 '21 at 12:43
  • How do you mean? `x` is an instance of the class, so `isinstance` returns `True`. Do you think it should not? – snakecharmerb Oct 21 '21 at 13:01
  • 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. – showkey Oct 21 '21 at 22:57
  • The purpose of the singleton design pattern is that there should only ever be one instance of the class, so instantiating the class should always return _the same instance_. The implementation in the question is lazy in the sense that the instance is not created until `get_instance()` is called. The ability to bypass `get_instance()` by instantiating the class directly is a defect in the implementation. I've demonstrated one way to fix this using `__new__`. See also [this Q&A](https://stackoverflow.com/q/6760685/5320906) for other ways to create singletons in Python. – snakecharmerb Oct 22 '21 at 07:31
  • I got a clear conclusion that it can't create a lazy instantiation with my two methods,is that true or not? – showkey Oct 22 '21 at 08:42
  • Yes - your class only works as a singleton if instances are always produces by calling `get_instance()` - if `Singleton()` is called then a new instance is produced instead the instance cached in `_instance`. – snakecharmerb Oct 22 '21 at 08:48