Mohammad Farjamfard
Mohammad Farjamfard

Reputation: 29

Python Singletons syntax and why its looks like that?

my first question here:

I've searched the internet and also read several question and answers here before and finally figured out the way of writing the singleton classes for my python codes. I've also read the python documentation about the new() function and some other things but still confused about how and what is mean by all that new(cls, *args, **kw) things etc!

for example I wrote a test code like this:

class Singleton(object):

    def __new__(cls, *args, **kwargs):
        if '_inst' not in vars(cls):
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

class printer(Singleton):

    def __init__(self):

        print "I am a new Object, and will remain until the end of time!"

if __name__ == '__main__':
    printer()

and the result is the text "I am a new Object, and will remain until the end of time!" But how this works, I mean, I don't know how to tell, for example I'm really confused about:

vars(cls): in the line if '_inst' not in vars(cls)

from where the vars(cls) comes out, I didn't declare that before! Can someone please clarify this things in the singleton class for me plus some about the last line

if __name__ == '__main__':
    printer()

Upvotes: 1

Views: 263

Answers (3)

Katriel
Katriel

Reputation: 123662

Instead of using a Singleton, have you considered using a Borg?

The idea is, because Python stores all the state for instances in an attribute (__dict__), if you simply reassign that attribute to a class attribute then you can instantiate the class as many times as they want but they will all have the same state.

Upvotes: 2

AndiDog
AndiDog

Reputation: 70148

First of all, this is wrong:

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if '_inst' not in vars(cls): # <-- this must of course also be "_instance"
            cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
        return cls._instance

An explicit __new__ method can be used like the factory pattern, so when you write printer(), Python will first call __new__, passing the class type and the constructor parameters (in this example none).

'_instance' not in vars(cls) just means to look up whether the class already has an attribute called "_instance" (i.e. the singleton). If not, one is created. The trick with vars (builtin function, to answer your question) is not necessary, one could also use cls._instance and catch AttributeError, for example.

And the last thing:

if __name__ == '__main__':
    printer()

This just creates a printer instance (using Singleton.__new__) if the script is executed directly (i.e. if __name__ == '__main__', not if the module is imported).

Upvotes: 2

gruszczy
gruszczy

Reputation: 42188

You should use modules as singletons in python, because they behave exactly like one.

Here is another question: Is there a simple, elegant way to define singletons?

Upvotes: 2

Related Questions