Questo in realtà deriva da una discussione qui su SO.Chi chiama la metaclasse
Versione corta
def meta(name, bases, class_dict)
return type(name, bases, class_dict)
class Klass(object):
__metaclass__ = meta
meta()
viene chiamato quando viene eseguito Klass
dichiarazione di classe.
Quale parte del codice (python internal) in realtà chiama meta()
?
Versione lunga
Quando la classe è dichiarata, del codice ha a che fare le opportune verifiche degli attributi e vedere se c'è un __metaclass__
dichiarata su un tipo. Se tale esiste, deve eseguire una chiamata di metodo su quel metaclass con i ben noti attributi (class_name, bases, class_dict)
. Non è chiaro per me quale codice sia responsabile per quella chiamata.
Ho fatto alcuni scavi in CPython (vedi sotto), ma mi piacerebbe davvero avere qualcosa di più vicino a una risposta definitiva.
Opzione 1: Chiamato direttamente
La chiamata metaclasse è cablato nel parsing di classe. Se è così, ci sono prove per questo?
Opzione 2: E 'chiamato dal type.__new__()
Codice in type_call()
chiamate type_new()
che a sua volta chiama _PyType_CalculateMetaclass()
. Questo suggerisce che la risoluzione metaclasse è in realtà fatto durante la chiamata a type()
quando si cerca di scoprire quale valore da restituire da type()
Ciò sarebbe in in linea con l'idea che una "classe" è un "richiamabile che restituisce un oggetto ".
Opzione 3: Qualcosa di diverso
Tutte le mie supposizioni forse completamente sbagliato, ovviamente.
Alcuni casi di esempio che ci siamo inventati in videochat:
Esempio 1:
class Meta(type):
pass
class A:
__metaclass__ = Meta
A.__class__ == Meta
Questo è ciò che Meta.__new__()
ritorni, quindi questo sembra legittimo. Il metaclasse si pone come A.__class__
Esempio 2:
class Meta(type):
def __new__(cls, class_name, bases, class_dict):
return type(class_name, bases, class_dict)
class A(object):
__metaclass__ = Meta
A.__class__ == type
Edit 2: corretta versione iniziale, derivano correttamente Meta
da type
.
Sembra ok, ma non sono sicuro che faccia ciò che penso. Inoltre: qual è il metodo canonico per farlo comportarsi come nell'esempio 1?
Edit 3: Utilizzo type.__new__(...)
sembra funzionare come previsto, che sembra anche a favore dell'opzione 2.
Può qualcuno con più approfondita conoscenza della magia python interno mi illumini?
Modifica: A per un primer abbastanza conciso su metaclassi: http://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/. Ha anche alcuni diagrammi davvero interessanti, riferimenti ed evidenzia anche le differenze tra python 2 e 3.
Edit 3: C'è una buona risposta per Python 3. Python 3 usa __build_class__
per creare un oggetto di classe. Il percorso del codice è, in ogni caso, diverso in Python 2.
http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python –
FWIW, la discussione originale riguardava se 'SomeClass()' risolve in 'SomeClass .__ class __.__ call __() '(che alla fine delegherà a' type .__ new __() ', o se iit si risolve a' type.__call __() '(che sarebbe il delegato a' SomeClass .__ class __.__ call__'). –
@brunodesthuilliers Penso che abbiamo risolto quello ed è il primo. Ancora alcuni enigmi si aprono, però :) – dhke