]> granicus.if.org Git - python/commitdiff
Improve performance of built-in any()/all() by avoiding PyIter_Next() --
authorGuido van Rossum <guido@python.org>
Thu, 20 Dec 2007 23:48:28 +0000 (23:48 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 20 Dec 2007 23:48:28 +0000 (23:48 +0000)
using a trick found in ifilter().
Feel free to backport to 2.5.

Python/bltinmodule.c

index 92304b3862ea97b927d94725fa4b281f09cfc88a..69969361c04e8f38f3b5fe1ae1d466f088d5aafb 100644 (file)
@@ -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;
 }