Cominciando super()
in sé è semplicemente un'abbreviazione per super(A, B)
, dove A
è la classe in cui si verifica il codice e B
è il primo argomento della funzione in cui si verifica il codice; Quindi nel tuo caso particolare, super().__new__(cls)
espande a super(CarModel, cls).__new__(cls)
.
A sua volta, super(T, O)
restituisce un "superoggetto". Per capire cosa fa un superoggetto, devi capire come funzionano i riferimenti di attributo su istanze e classi in Python.
assumendo alcun __getattr__
o __getattribute__
metodi sono coinvolti, referenziare attributo A
su un oggetto O
(cioè, valutando O.A
o getattr(O, "A")
) procede attraverso le seguenti fasi:
- Se
"A"
è definita esempio O
s' dict (O.__dict__
), allora il valore che dict è riportato direttamente, proprio come è.
- In caso contrario, ciascuna delle classi nell'ordine di risoluzione dei metodi di
O
viene verificata a turno, cercando "A"
in ciascuno dei propri dict. Se trovato, chiama il valore D
.
- Se
D
, a sua volta, non definisce un __get__
, quindi viene restituito così com'è.Se lo fa, però, quindi D
viene definito come un "descrittore", e il suo metodo __get__
è chiamato con O
come primo argomento, e type(O)
come secondo argomento.
Un riferimento attributo per una classe funziona sullo stesso, sostituendo il riferimento essendo classe per l'istanza, con le seguenti differenze:
- Fase 1 non si applica.
- Procedimento
__get__
è chiamato con None
come primo argomento, e la classe essendo fatto riferimento come secondo.
Python utilizza descrittori per implementare cose come metodi di istanza, metodi di classe, metodi statici e proprietà.
Un super oggetto creato con super(T, O)
, poi, è un oggetto (built-in) con un metodo __getattribute__
che è chiamato ad ogni attributo di riferimento su di esso, e cerca l'attributo nelle dicts delle uniche classi seguenti T nel MRO di O
. Il valore che trova poi, chiama __get__
come al solito.
il processo è un po 'complessa, così come un esempio, ecco come avrebbe funzionato sul vostro caso specifico. Poiché CarModel
è definito così com'è, il suo MRO è [CarModel, object]
.
super().__new__(cls)
si espande a super(CarModel, cls).__new__(cls)
, come descritto sopra.
super(CarModel, cls)
viene valutata per produrre un super oggetto S
.
- Python recupera l'attributo
"__new__"
su S
(l'equivalente di chiamare getattr(S, "__new__")
in codice Python).
- Da
S
stata creata sulla classe CarModel
, considera le classi seguenti CarModel
nel MRO di CarModel
, e trova "__new__"
nel dict della classe object
stessa. Il suo valore, un metodo statico, ha un metodo __get__
, che viene chiamata con gli argomenti None
e cls
. Poiché __new__
è un metodo statico, il suo metodo __get__
restituisce semplicemente la funzione così com'è, non modificata. Pertanto, super(CarModel, cls).__new__
corrisponde esattamente a object.__new__
.
- La funzione ottenuto nel passaggio precedente (cioè,
object.__new__
) viene richiamato con l'argomento cls
, dove cls
è probabilmente CarModel
, infine una nuova istanza della classe CarModel
.
spero che era affatto comprensibile.
(Per ragioni di completezza, si segnala che la funzione effettiva __new__
sulla classe object
non è effettivamente un metodo statico, ma una speciale funzione incorporata che ha semplicemente alcun metodo __get__
affatto, ma poiché la Il metodo __get__
su metodi statici restituisce semplicemente la funzione con cui sono stati definiti, l'effetto è lo stesso.)
@Ben, basato sul [documento] (http://docs.python.org/py3k/reference/datamodel.html # objects-values-and-types), '__new __()' restituisce un'istanza di 'cls'. perché il codice 'model = super() .__ new __ (cls) ' in OP può creare un'istanza di 'cls'? In che modo la super classe di CarModel sa come creare un'istanza della sua sottoclasse? – q0987
Questa sarebbe una grande domanda SO da sola (se non è già stata richiesta). La risposta breve è che passi la classe corrente con il parametro 'cls'. In definitiva, non c'è assolutamente modo di creare una nuova istanza senza rimandare completamente a 'object .__ new__', perché Python non ha istruzioni per" allocare un'istanza ". Ma 'object .__ new__' sa di creare un'istanza della classe passata (che sarà anche un'istanza di' object', perché tutto è un'istanza di 'object'). – Ben