Issue #2534: speed up isinstance() and issubclass() by 50-70%, so as to
match Python 2.5 speed despite the __instancecheck__ / __subclasscheck__
mechanism. In the process, fix a bug where isinstance() and issubclass(),
when given a tuple of classes as second argument, were looking up
__instancecheck__ / __subclasscheck__ on the tuple rather than on each
type object.
Reviewed by Benjamin Peterson and Raymond Hettinger.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 02b5012..405b773 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -571,6 +571,49 @@
return result;
}
+static PyObject *
+type___instancecheck__(PyObject *type, PyObject *inst)
+{
+ switch (_PyObject_RealIsInstance(inst, type)) {
+ case -1:
+ return NULL;
+ case 0:
+ Py_RETURN_FALSE;
+ default:
+ Py_RETURN_TRUE;
+ }
+}
+
+
+static PyObject *
+type_get_instancecheck(PyObject *type, void *context)
+{
+ static PyMethodDef ml = {"__instancecheck__",
+ type___instancecheck__, METH_O };
+ return PyCFunction_New(&ml, type);
+}
+
+static PyObject *
+type___subclasscheck__(PyObject *type, PyObject *inst)
+{
+ switch (_PyObject_RealIsSubclass(inst, type)) {
+ case -1:
+ return NULL;
+ case 0:
+ Py_RETURN_FALSE;
+ default:
+ Py_RETURN_TRUE;
+ }
+}
+
+static PyObject *
+type_get_subclasscheck(PyObject *type, void *context)
+{
+ static PyMethodDef ml = {"__subclasscheck__",
+ type___subclasscheck__, METH_O };
+ return PyCFunction_New(&ml, type);
+}
+
static PyGetSetDef type_getsets[] = {
{"__name__", (getter)type_name, (setter)type_set_name, NULL},
{"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL},
@@ -579,6 +622,8 @@
(setter)type_set_abstractmethods, NULL},
{"__dict__", (getter)type_dict, NULL, NULL},
{"__doc__", (getter)type_get_doc, NULL, NULL},
+ {"__instancecheck__", (getter)type_get_instancecheck, NULL, NULL},
+ {"__subclasscheck__", (getter)type_get_subclasscheck, NULL, NULL},
{0}
};