Creating singleton class in python

I'm reading through http://blog.thedigitalcatonline.com/blog/2014/09/01/python-3-oop-part-5-metaclasses/#.VwPSjDG1XGD. In it, they have:

class Singleton(type):
    instance = None
    def __call__(cls, *args, **kw):
        if not cls.instance:
             cls.instance = super(Singleton, cls).__call__(*args, **kw)
        return cls.instance

The explanation is:

We are defining a new type, which inherits from type to provide all bells and whistles of Python classes. We override the call method, that is a special method invoked when we call the class, i.e. when we instance it. The new method wraps the original method of type by calling it only when the instance attribute is not set, i.e. the first time the class is instanced, otherwise it just returns the recorded instance. As you can see this is a very basic cache class, the only trick is that it is applied to the creation of instances.

I'm not sure I understand the line:

cls.instance = super(Singleton, cls).__call__(*args, **kw)

Can someone explain what is happening here in another way?

Answers


By default, __call__ing on a class object produces an instance of such class (remember that classes are callables like functions, in contrast to other languages like PHP where they are completely separate monsters in their interface). This instance will be stored in cls.instance.

cls.instance = super(Singleton, cls).__call__(*args, **kw)

By wrapping in the previous condition, if the instance is already an... instance, it is returned. This means: stuff like __new__ is not called on the class again, and stuff like __init__ is not called on the instance again, but just returned the old -already existent- instance.

Notes: When you call __call__ in the default implementation, the __new__ method is called for the class (it is always a class method; you never use the @classmethod decorator there) to create the instance. After that, the __init__ message is sent to the instance to initialize it.

Notes on Metaclasses: Remember that Singleton is not an usual class, but a Metaclass. It is not a class you will inherit from, but a Metaclass you will instantiate your class with.

Objects are instances of Classes, and Classes are instances of Metaclasses (which may confuse you since they are also classes). This means that there's a closed loop in which the reference type is an instance of itself:

assert isinstance(type, type)

There, your code will come like this:

class MySingletonClass(object):
    __metaclass__ = Singleton

And the magic will begin:

  1. The __call__ method you are overriding with your code will be executed on the class since it is defined on the metaclass (Singleton). This means:

    i = MySingletonClass() # Executes what is defined in Singleton as __call__
    

    You should not confuse with this one:

    i() # Will crash if MySingletonClass does not define __call__ for its instances.
    
  2. The call you are making in your code has another equivalent:

    super(Singleton, cls).__call__(*a, **kwa)
    

    Is the same as:

    (a type isntance)(*a, **kwa)
    

    Or

    (a type isntance).__call__(*a, **kwa)
    

    Which is the same behavior every class, not using a custom metaclass like yours, uses to create their instances.


Need Your Help

Get QThread that created QObject

c++ multithreading qt qthread

Some QThread * worker has created QObject *tmp = new QObject(). How can another thread identify the worker given tmp? Is there something like:

Exc_bad_acces in didUpdateLocations when app becomes active

ios iphone exc-bad-access cllocationmanager cllocation

In my iOS7 app I have a singleton called ICVModel. When the app starts this singleton gets initialized and creates CLLocationManager which immediately starts updating location. This works fine,