Home > Net >  two issues on the lazy instantiation in the Singleton pattern
two issues on the lazy instantiation in the Singleton pattern

Time:10-24

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.

  • Related