mirror of https://github.com/python/cpython
bpo-32379: Faster MRO computation for single inheritance (#4932)
* bpo-32379: Faster MRO computation for single inheritance
This commit is contained in:
parent
776407fe89
commit
1f1a34c314
|
@ -1783,6 +1783,12 @@ order (MRO) for bases """
|
||||||
def f(self): return "C"
|
def f(self): return "C"
|
||||||
class D(B, C):
|
class D(B, C):
|
||||||
pass
|
pass
|
||||||
|
self.assertEqual(A.mro(), [A, object])
|
||||||
|
self.assertEqual(A.__mro__, (A, object))
|
||||||
|
self.assertEqual(B.mro(), [B, A, object])
|
||||||
|
self.assertEqual(B.__mro__, (B, A, object))
|
||||||
|
self.assertEqual(C.mro(), [C, A, object])
|
||||||
|
self.assertEqual(C.__mro__, (C, A, object))
|
||||||
self.assertEqual(D.mro(), [D, B, C, A, object])
|
self.assertEqual(D.mro(), [D, B, C, A, object])
|
||||||
self.assertEqual(D.__mro__, (D, B, C, A, object))
|
self.assertEqual(D.__mro__, (D, B, C, A, object))
|
||||||
self.assertEqual(D().f(), "C")
|
self.assertEqual(D().f(), "C")
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Make MRO computation faster when a class inherits from a single base.
|
|
@ -1761,6 +1761,36 @@ mro_implementation(PyTypeObject *type)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bases = type->tp_bases;
|
||||||
|
n = PyTuple_GET_SIZE(bases);
|
||||||
|
if (n == 1) {
|
||||||
|
/* Fast path: if there is a single base, constructing the MRO
|
||||||
|
* is trivial.
|
||||||
|
*/
|
||||||
|
PyTypeObject *base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0);
|
||||||
|
Py_ssize_t k;
|
||||||
|
|
||||||
|
if (base->tp_mro == NULL) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"Cannot extend an incomplete type '%.100s'",
|
||||||
|
base->tp_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
k = PyTuple_GET_SIZE(base->tp_mro);
|
||||||
|
result = PyTuple_New(k + 1);
|
||||||
|
if (result == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_INCREF(type);
|
||||||
|
PyTuple_SET_ITEM(result, 0, (PyObject *) type);
|
||||||
|
for (i = 0; i < k; i++) {
|
||||||
|
PyObject *cls = PyTuple_GET_ITEM(base->tp_mro, i);
|
||||||
|
Py_INCREF(cls);
|
||||||
|
PyTuple_SET_ITEM(result, i + 1, cls);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* Find a superclass linearization that honors the constraints
|
/* Find a superclass linearization that honors the constraints
|
||||||
of the explicit lists of bases and the constraints implied by
|
of the explicit lists of bases and the constraints implied by
|
||||||
each base class.
|
each base class.
|
||||||
|
@ -1770,9 +1800,6 @@ mro_implementation(PyTypeObject *type)
|
||||||
to_merge is the declared list of bases.
|
to_merge is the declared list of bases.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bases = type->tp_bases;
|
|
||||||
n = PyTuple_GET_SIZE(bases);
|
|
||||||
|
|
||||||
to_merge = PyList_New(n+1);
|
to_merge = PyList_New(n+1);
|
||||||
if (to_merge == NULL)
|
if (to_merge == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1830,7 +1857,12 @@ static PyObject *
|
||||||
type_mro_impl(PyTypeObject *self)
|
type_mro_impl(PyTypeObject *self)
|
||||||
/*[clinic end generated code: output=bffc4a39b5b57027 input=28414f4e156db28d]*/
|
/*[clinic end generated code: output=bffc4a39b5b57027 input=28414f4e156db28d]*/
|
||||||
{
|
{
|
||||||
return mro_implementation(self);
|
PyObject *seq;
|
||||||
|
seq = mro_implementation(self);
|
||||||
|
if (seq != NULL && !PyList_Check(seq)) {
|
||||||
|
Py_SETREF(seq, PySequence_List(seq));
|
||||||
|
}
|
||||||
|
return seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
Loading…
Reference in New Issue