Para comenzar con super()
en sí mismo es simplemente la abreviatura de super(A, B)
, donde A
es la clase en la que se produce el código, y B
es el primer argumento de la función en la que se produce el código; entonces en su caso particular, super().__new__(cls)
se expande a super(CarModel, cls).__new__(cls)
.
A su vez, super(T, O)
devuelve un "súper objeto". Para comprender lo que hace un súper objeto, necesita comprender cómo funcionan las referencias de atributos en instancias y clases en Python.
suponiendo que no hay __getattr__
o __getattribute__
métodos están involucrados, haciendo referencia a atributo A
sobre un objeto O
(es decir, la evaluación de O.A
o getattr(O, "A")
) procede a través de los siguientes pasos:
- Si
"A"
se define en la instancia O
's dict (O.__dict__
), entonces el valor en ese dict se devuelve directamente, precisamente como es.
- De lo contrario, cada una de las clases en el orden de resolución de método
O
se comprueban sucesivamente, buscando "A"
en cada uno de sus dictados. Si se encuentra, llame al valor D
.
- Si
D
, a su vez, no define un __get__
, entonces se devuelve tal como está.Si lo hace, sin embargo, entonces D
se conoce como un "descriptor", y se llama a su método __get__
con O
como primer argumento, y type(O)
como el segundo argumento.
Una referencia atributo en una clase de trabajos sobre el mismo, la sustitución de la clase siendo referencia para el ejemplo, con las siguientes diferencias:
- Paso 1 no se aplica.
- Se llama al método
__get__
con None
como primer argumento, y la clase a la que se hace referencia como segunda.
Python utiliza descriptores para implementar cosas tales como métodos de instancia, métodos de clase, métodos estáticos y propiedades.
Un objeto súper creada con super(T, O)
, entonces, es un objeto (built-in) con un método __getattribute__
que se llama en cada atributo de referencia en él, y busca el atributo en los dicts de los sólo las clases siguientes T en O
MRO. El valor que encuentra, llama al __get__
como de costumbre.
El proceso es un poco complejo, por ejemplo, así es como funcionaría en su caso específico. Como CarModel
se define tal como es, su MRO es [CarModel, object]
.
super().__new__(cls)
se expande a super(CarModel, cls).__new__(cls)
, como se describió anteriormente.
super(CarModel, cls)
se evalúa para generar un superobjeto S
.
- Python obtiene el atributo
"__new__"
en S
(el equivalente a llamar a getattr(S, "__new__")
en código Python).
- Desde
S
fue creado en la clase CarModel
, considera las siguientes clases CarModel
en el MRO de CarModel
, y encuentra "__new__"
en el dict de la clase object
sí. Su valor, un método estático, tiene un método __get__
, que se llama con los argumentos None
y cls
. Como __new__
es un método estático, su método __get__
simplemente devuelve la función tal como está, sin modificaciones. Por lo tanto, super(CarModel, cls).__new__
es exactamente lo mismo que object.__new__
.
- La función obtenida en el paso anterior (es decir,
object.__new__
) se llama con el argumento cls
, donde cls
es probablemente CarModel
, por último, una nueva instancia de la clase CarModel
.
Espero que sea del todo comprensible.
(Para mayor abundamiento, cabe mencionar que el __new__
función real de la clase object
no es en realidad un método estático, sino una función incorporada en especial que simplemente no tiene un método __get__
en absoluto, pero dado que el __get__
método en métodos estáticos simplemente devuelve la función con la que se definieron, el efecto es el mismo.)
@Ben, basado en el [documento] (http://docs.python.org/py3k/reference/datamodel.html # objects-values-and-types), '__new __()' devuelve una instancia de 'cls'. ¿por qué el código 'modelo = super() .__ nuevo __ (cls) ' en OP puede crear una instancia de 'cls'? ¿Cómo sabe la súper clase de CarModel cómo crear una instancia de su subclase? – q0987
Esa sería una gran pregunta SO por sí misma (si aún no se ha hecho). La respuesta corta es que le está pasando la clase actual con el parámetro 'cls'. En última instancia, no hay forma de crear realmente una instancia nueva sin retrasar todo el camino de regreso a 'object .__ new__', porque Python no tiene instrucciones para" asignar una instancia ". Pero 'object .__ new__' sabe crear una instancia de la clase que ha pasado (que también será una instancia de' object', porque todo es una instancia de 'object'). – Ben