What does `super ()` do in `__new__`

Note: part of flyweight implementation with Python

import weakref class CarModel: _models = weakref.WeakValueDictionary() def __new__(cls, model_name, *args, **kwargs): model = cls._models.get(model_name) if not model: model = super().__new__(cls) cls._models[model_name] = model return model def __init__(self, model_name, air=False): if not hasattr(self, "initted"): self.model_name = model_name self.air = air self.initted=True 

Question 1> what does super() mean? Does this mean the parent CarModel class?

Question 2> I also find it difficult to understand how the __new__ function __new__ ? In particular, the next line.

 model = super().__new__(cls) 

Description for __new__ :

The constructor function is called __new__ , unlike __init__ , and takes exactly one argument, the class that is being built (it is called before the object is built, so there is no argument). It must also return the newly created object.

+6
source share
3 answers

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.)

+11
source

super() used to refer to a superclass (i.e. the parent class from which you are a subclass).

__new__ is the method that is called to create a new instance of the class, if one is defined.

+1
source

I believe you are using Python3 where super does not need to be provided with the same class name. Super refers to the base classes of the current class and does the correct order of method resolution for calling the method from the correct base class. __new__ is the method that is called to create the instance. This is the first step in creating an instance .

+1
source

Source: https://habr.com/ru/post/907176/


All Articles