[Python-checkins] bpo-32379: Faster MRO computation for single inheritance (#4932)
Antoine Pitrou
webhook-mailer at python.org
Wed Dec 20 09:58:24 EST 2017
https://github.com/python/cpython/commit/1f1a34c3145781628e10534440017b3b43211a60
commit: 1f1a34c3145781628e10534440017b3b43211a60
branch: master
author: Antoine Pitrou <pitrou at free.fr>
committer: GitHub <noreply at github.com>
date: 2017-12-20T15:58:21+01:00
summary:
bpo-32379: Faster MRO computation for single inheritance (#4932)
* bpo-32379: Faster MRO computation for single inheritance
files:
A Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst
M Lib/test/test_descr.py
M Objects/typeobject.c
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
index ced25f3fc44..d24d005ccfa 100644
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1783,6 +1783,12 @@ class C(A):
def f(self): return "C"
class D(B, C):
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().f(), "C")
diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst b/Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst
new file mode 100644
index 00000000000..1050c61b9ec
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2017-12-19-21-14-41.bpo-32379.B7mOmI.rst
@@ -0,0 +1 @@
+Make MRO computation faster when a class inherits from a single base.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index aa907018859..849c6dc1929 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1761,6 +1761,36 @@ mro_implementation(PyTypeObject *type)
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
of the explicit lists of bases and the constraints implied by
each base class.
@@ -1770,9 +1800,6 @@ mro_implementation(PyTypeObject *type)
to_merge is the declared list of bases.
*/
- bases = type->tp_bases;
- n = PyTuple_GET_SIZE(bases);
-
to_merge = PyList_New(n+1);
if (to_merge == NULL)
return NULL;
@@ -1830,7 +1857,12 @@ static PyObject *
type_mro_impl(PyTypeObject *self)
/*[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
More information about the Python-checkins
mailing list