From: Guido van Rossum Date: Thu, 20 Dec 2007 23:48:28 +0000 (+0000) Subject: Improve performance of built-in any()/all() by avoiding PyIter_Next() -- X-Git-Tag: v2.6a1~818 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=01dbc109a83b17e19f3da1da9572b6de17add502;p=python Improve performance of built-in any()/all() by avoiding PyIter_Next() -- using a trick found in ifilter(). Feel free to backport to 2.5. --- diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 92304b3862..69969361c0 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -78,13 +78,19 @@ static PyObject * builtin_all(PyObject *self, PyObject *v) { PyObject *it, *item; + PyObject *(*iternext)(PyObject *); + int cmp; it = PyObject_GetIter(v); if (it == NULL) return NULL; + iternext = *Py_TYPE(it)->tp_iternext; - while ((item = PyIter_Next(it)) != NULL) { - int cmp = PyObject_IsTrue(item); + for (;;) { + item = iternext(it); + if (item == NULL) + break; + cmp = PyObject_IsTrue(item); Py_DECREF(item); if (cmp < 0) { Py_DECREF(it); @@ -96,8 +102,12 @@ builtin_all(PyObject *self, PyObject *v) } } Py_DECREF(it); - if (PyErr_Occurred()) - return NULL; + if (PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_StopIteration)) + PyErr_Clear(); + else + return NULL; + } Py_RETURN_TRUE; } @@ -110,13 +120,19 @@ static PyObject * builtin_any(PyObject *self, PyObject *v) { PyObject *it, *item; + PyObject *(*iternext)(PyObject *); + int cmp; it = PyObject_GetIter(v); if (it == NULL) return NULL; + iternext = *Py_TYPE(it)->tp_iternext; - while ((item = PyIter_Next(it)) != NULL) { - int cmp = PyObject_IsTrue(item); + for (;;) { + item = iternext(it); + if (item == NULL) + break; + cmp = PyObject_IsTrue(item); Py_DECREF(item); if (cmp < 0) { Py_DECREF(it); @@ -128,8 +144,12 @@ builtin_any(PyObject *self, PyObject *v) } } Py_DECREF(it); - if (PyErr_Occurred()) - return NULL; + if (PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_StopIteration)) + PyErr_Clear(); + else + return NULL; + } Py_RETURN_FALSE; }