For starters, super()
itself is simply an abbreviation for super(A, B)
, where A
is the class in which the code occurs, and B
is the first argument to the function in which the code occurs; therefore, in your specific case, super().__new__(cls)
expands to super(CarModel, cls).__new__(cls)
.
In turn, super(T, O)
returns a "super object". To understand what a super object does, you need to understand how instance and class references work in Python.
Assuming that the __getattr__
or __getattribute__
not involved, a reference to the A
attribute on the O
object (that is, the OA
evaluation or getattr(O, "A")
) is performed using the following steps:
- If
"A"
is defined in an O
instance dict ( O.__dict__
), then the value on that dict is returned directly, just like it is. - Otherwise, each of the classes in order of resolution of method
O
checked one by one, looking for "A"
in each of its dicts. If found, call the value D
- If
D
, in turn, does not define a __get__
, then it returns as is. However, if that is the case, then D
is referred to as a “descriptor”, and its __get__
method __get__
called with O
as the first argument, and type(O)
as the second argument.
An attribute reference for a class works approximately the same, replacing the class with an instance reference, with the following differences:
- Step 1 does not apply.
- The
__get__
method __get__
called with None
as the first argument, and the class is referenced as the second.
Python uses descriptors to implement such things as instance methods, class methods, static methods, and properties.
A super object created using super(T, O)
is then an (inline) object with the __getattribute__
method, which is called on every attribute link on it and searches for the attribute in dicts of only classes after T in O
MRO. The value he finds calls __get__
as usual.
The process is a bit complicated, for example, here, how it will work in your particular case. Since CarModel
defined as is, its MRO [CarModel, object]
.
super().__new__(cls)
expands to super(CarModel, cls).__new__(cls)
as described above.super(CarModel, cls)
is evaluated to get the super object S
- Python retrieves the
"__new__"
attribute in S
(the equivalent of calling getattr(S, "__new__")
in Python code). - Since
S
was created in the CarModel
class, it examines the classes following the CarModel
in the MRO CarModel
, and finds "__new__"
in the sentence of the object
class. Its value, the static method, has the __get__
method, which is called with the arguments None
and cls
. Since __new__
is a static method, its __get__
method simply returns the function as it is, unmodified. Therefore, super(CarModel, cls).__new__
exactly the same as object.__new__
. - The function obtained in the last step (i.e.
object.__new__
) is called with the cls
argument, where cls
is probably CarModel
, finally a new instance of the CarModel
class.
Hope this was perfectly clear.
(For completeness, it should be mentioned that the actual __new__
function in the object
class is actually not a static method, but a special built-in function that simply does not have the __get__
method for everything, but since the __get__
method for static methods simply returns the function with which they were defined, the effect is the same.)