Reputation: 3956
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?
Upvotes: 3
Views: 324
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