Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explain python Singleton class

class Singleton:

    instance = None

    def __new__(cls):
        if cls.instance is None:
            cls.instance = super().__new__(cls)
        return cls.instance

singleton_obj1 = Singleton()
singleton_obj2 = Singleton()

print(singleton_obj1)
print(singleton_obj2)

output

<__main__.Singleton object at 0x10dbc0f60>
<__main__.Singleton object at 0x10dbc0f60>

Can someone explain what exactly happening at this line cls.instance = super().__new__(cls). Which lines of code helped to make this class Singleton?

like image 831
lch Avatar asked Jun 11 '18 19:06

lch


1 Answers

Ok, to go over this in painful detail:

class Singleton: implicitly inherits from Object because in python everything is an Object.

instance = None is only read at module load time, and sets the class level variable instance to be None one time but it can be over written by individual instances of the class Singleton.

def __new__(cls):
    if cls.instance is None:
        cls.instance = super().__new__(cls)
    return cls.instance

(First off, I think that it's weird that they put "cls" in there, I know why they did it, because it's referring to the class overall and not a specific instance of that class. But, it can be confusing so someone who doesn't know what they're looking at. Anyway...)

__new__ is a magic function that is called before __init__, that is roughly analogous to allocating the space for the new instance of the class. Here, cls.instance was set to None on module load, and so every time a new Singleton is being created this test is done. Since cls.instance is set the first time a Singleton is created, the super().__new__(cls) is also only called once. The super class of Singleton is Object. So the behavior of the super().__new__(cls) is exactly what you'd expect it to be for any other class you create.
If, you are creating a second(, or third/fourth/fifth...) instance of Singleton then this super().__new__(cls) will not be called. Instead the class level variable instance is returned, meaning that no new instances of Singleton can be created.

When you print the instances of Singleton then you can see the memory address of 0x10dbc0f60 is the same for both "instances" because cls.instance is returned at __new__ time, which you can think of as memory allocation time, before __init__ is called.

This is a good way to do a Singleton pattern because in order to create a singleton class, now, all you have to do is inherit from Singleton and the heavy lifting is already done. You go ahead and use __init__ like you normally would, and don't worry about it. Every time you go to create a "new" instance of that class, you'll get the same instance back. Totally behind the scenes.

This is pretty advanced stuff, but look how simple it is. python is the best!

like image 66
VoNWooDSoN Avatar answered Sep 28 '22 06:09

VoNWooDSoN