Cet article présente principalement le problème de la surcharge de la relation d'héritage isinstance en Python. Il a une certaine valeur de référence. Maintenant, je le partage avec vous. Les amis dans le besoin peuvent se référer à
pour le jugement de la relation d'héritage.
À l'aide de la méthode intégrée isinstance(object, classinfo), vous pouvez déterminer si un objet est une instance d'une certaine classe. Cette relation peut être directe, indirecte ou abstraite.
Les vérifications d'instance peuvent être surchargées, voir le document personnalisation des vérifications d'instance et de sous-classe. D'après la description du PEP 3119 :
Seul False est imprimé et __instancecheck__ n'est pas appelé. Que se passe-t-il.Le mécanisme principal proposé ici est de permettre la surcharge des fonctions intégrées isinstance() et issubclass() : L'appel isinstance(x. , C ) vérifie d'abord si C.__instancecheck__ existe, et si c'est le cas, appelle C.__instancecheck__(x) au lieu de son implémentation normale, C) Lors de la détection, il vérifiera d'abord si C.__instancecheck__ existe. .__instancecheck__(x) sera appelé. Le résultat renvoyé est le résultat de la détection d'instance et il n'y a pas de méthode de jugement par défaut.
Cette méthode nous aide à vérifier la frappe du canard, je l'ai testée avec du code.
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
On peut voir que le document n'est pas clairement écrit Afin de découvrir le problème, nous commençons le traçage à partir de. le code source d'isinstance.
[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); }
[object.h] #define PyType_CheckExact(op) (Py_TYPE(op) == &PyType_Type)
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 False
if (PyTuple_Check(cls)) { ... }
checker = _PyObject_LookupSpecial(cls, &PyId___instancecheck__); if (checker != NULL) { res = PyObject_CallFunctionObjArgs(checker, inst, NULL); ok = PyObject_IsTrue(res); return ok; }
[typeobject.c] PyObject * _PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid) { PyObject *res; res = _PyType_LookupId(Py_TYPE(self), attrid); // 有回调的话处理回调 // ... return res; }
À ce stade, résumez les conditions de surcharge du comportement isinstance(x, C) :
x les objets ne peuvent pas être directement instanciés par C ;
La classe C spécifie la métaclasse
__instancecheck__ est définie dans la métaclasse spécifiée ;
Code de test :
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
Explication détaillée de read_excel dans Python 2.7 pandas
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!