techkuz
techkuz

Reputation: 3956

What does super(subclass, class).__new__(class) do?

In the following Python implementation of the Singleton pattern:

class Singleton(object):
    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance

What does the line cls.instance = super(Singleton, cls).__new__(cls) do?

Among other things in this line that I don't understand is the super usage. I saw usage of super with (subclass, instance), but here we pass it (subclass, class). So is it going to have (Singleton class, Singleton class) as arguments?

Live example

Upvotes: 3

Views: 324

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1122552

The second argument to super() is used for two purposes:

  • To supply an ordered list of classes to search through; the order is the Method Resolution Order (MRO), and searching for attributes on super() starts at the class following the one named as the first argument to super()

  • To bind any descriptors (like methods) to.

So super(clsobject, second_argument) will look for a __mro__ list, then search for clsobject, then continue searching the remainder of the list for the attribute you wanted. It then uses the descriptor protocol to bind the object to second_argument.

The __new__ method only makes sense on a class, because it creates a new instance; there is no instance yet when that method is called; it is the factory that is supposed to produce the instance for that class.

So you can't pass in an instance as the second argument. You can only pass in a class, and super() can handle that. For instances, super() looks at type(instance).__mro__, but for classes, classobject.__mro__ is used instead. So passing in cls is perfectly fine here.

__new__ is also a static method, meaning that it ignores the binding process. No automatic passing in of the first argument, the class, takes place. You need to do this manually, hence the ...__new__(cls) call.

So in this specific instance, the line:

cls.instance = super(Singleton, cls).__new__(cls)

will search for Singleton in cls.__mro__, find the next object with a __new__ attribute, and then try to bind that __new__ attribute to cls. If you didn't use multiple inheritance, that is going to be object.__new__. The __new__ method is static, so no binding takes place, so you are given object.__new__, which is then called with cls as the first argument. This produces an instance of the Singleton class (or a subclass thereof), which is then assigned to the attribute instance on the class object.

Upvotes: 6

Related Questions