Heim > Artikel > Backend-Entwicklung > Eine kurze Diskussion zum Problem der Überlastung istInstanzvererbungsbeziehung in Python
Dieser Artikel befasst sich hauptsächlich mit dem Problem der Überlastung der Vererbungsbeziehung. Jetzt können Freunde in Not auf die Vererbungsbeziehung zurückgreifen
Mit der integrierten Methode isinstance(object, classinfo) können Sie feststellen, ob ein Objekt eine Instanz einer bestimmten Klasse ist. Diese Beziehung kann direkt, indirekt oder abstrakt sein.
Der hier vorgeschlagene primäre Mechanismus besteht darin, das Überladen der integrierten Funktionen isinstance() und issubclass() zu ermöglichen. Das Überladen funktioniert wie folgt: Der Aufruf isinstance(x , C) prüft zunächst, ob C.__instancecheck__ existiert, und ruft in diesem Fall C.__instancecheck__(x) anstelle seiner normalen Implementierung auf. , C) Bei der Erkennung wird zunächst geprüft, ob C.__instancecheck__ existiert .__instancecheck__(x) wird aufgerufen. Das zurückgegebene Ergebnis ist das Ergebnis der Instanzerkennung, und es gibt keine Standardbeurteilungsmethode.
Diese Methode hilft uns, die Enteneingabe zu überprüfen. Ich habe sie mit Code getestet.Es wird nur False ausgegeben und __instancecheck__ wird nicht aufgerufen. Was ist los.
class Sizeable(object): def __instancecheck__(cls, instance): print("__instancecheck__ call") return hasattr(instance, "__len__") class B(object): pass b = B() print(isinstance(b, Sizeable)) # output:False
Es gibt keinen laufenden __instancecheck__
Es ist ersichtlich, dass das Dokument nicht klar geschrieben ist. Um das Problem herauszufinden, beginnen wir mit der Nachverfolgung der isinstance-Quellcode.
[abstract.c]
int
PyObject_IsInstance(PyObject *inst, PyObject *cls)
{
_Py_IDENTIFIER(__instancecheck__);
PyObject *checker;
/* Quick test for an exact match */
if (Py_TYPE(inst) == (PyTypeObject *)cls)
return 1;
....
}
/* We know what type's __instancecheck__ does. */ if (PyType_CheckExact(cls)) { return recursive_isinstance(inst, cls); }Erweitern Sie das Makro PyType_CheckExact:
[object.h] #define PyType_CheckExact(op) (Py_TYPE(op) == &PyType_Type)Das heißt, wenn cls eine Klasse ist, die direkt aus dem Typ erstellt wird, dann ist die Beurteilungssprache etabliert. Mit Ausnahme der in der Klassendeklaration angegebenen Metaklasse wird sie grundsätzlich direkt nach Typ erstellt. Wenn Sie anhand des Testcodes wissen, dass das Urteil gefällt wurde, geben Sie recursive_isinstance ein. Aber ich habe den Code zu __instancecheck__ in dieser Funktion nicht gefunden. Die Beurteilungslogik von recursive_isinstance lautet ungefähr:
def recursive_isinstance(inst, cls): return pyType_IsSubtype(inst, cls) def pyType_IsSubtype(a, b): for mro in a.__mro__: if mro is b: return True return Falsewird anhand der __mro__-Vererbungsreihenfolge beurteilt. Gehen Sie zurück zur Funktion PyObject_IsInstance und schauen Sie nach unten:
if (PyTuple_Check(cls)) { ... }Dies ist der Fall, wenn der zweite Parameter von Instanz(x, C) ein Tupel ist und der Verarbeitungsmethode im Inneren Es handelt sich um einen rekursiven Aufruf von PyObject_IsInstance(inst, item). Weiterlesen:
checker = _PyObject_LookupSpecial(cls, &PyId___instancecheck__); if (checker != NULL) { res = PyObject_CallFunctionObjArgs(checker, inst, NULL); ok = PyObject_IsTrue(res); return ok; }Hier wird natürlich __instancecheck__ abgerufen, um den Prüfvorgang an diesen Punkt zu bringen, muss die definierte Klasse metaclass angeben. Jetzt müssen Sie nur noch _PyObject_LookupSpecial verfolgen:
[typeobject.c] PyObject * _PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid) { PyObject *res; res = _PyType_LookupId(Py_TYPE(self), attrid); // 有回调的话处理回调 // ... return res; }nimmt Py_TYPE(self) an, was bedeutet, dass __instancecheck__ in der angegebenen Metaklasse definiert werden muss.
Zusammenfassung
An dieser Stelle fassen Sie die Bedingungen für das Überlastungsverhalten von isinstance(x, C) zusammen:
x-Objekte können nicht direkt von C instanziiert werden;
class MetaSizeable(type): def __instancecheck__(cls, instance): print("__instancecheck__ call") return hasattr(instance, "__len__") class Sizeable(metaclass=MetaSizeable): pass class B(object): pass b = B() print(isinstance(b, Sizeable)) # output: False print(isinstance([], Sizeable)) # output: True
Verwandte Empfehlungen:
Detaillierte Erklärung von read_excel in Python 2.7 Pandas
Das obige ist der detaillierte Inhalt vonEine kurze Diskussion zum Problem der Überlastung istInstanzvererbungsbeziehung in Python. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!