Mercurial > cpython-lru_cache-weakref
diff Python/bltinmodule.c @ 17677:bf7f166d3c97 legacy-trunk
Generalize reduce() to work with iterators.
NEEDS DOC CHANGES.
| author | Tim Peters <tim.peters@gmail.com> |
|---|---|
| date | Fri, 04 May 2001 04:39:21 +0000 |
| parents | 0be277039d93 |
| children | e9a4e27e8d4e |
line wrap: on
line diff
--- a/Python/bltinmodule.c Thu May 03 23:58:47 2001 +0000 +++ b/Python/bltinmodule.c Fri May 04 04:39:21 2001 +0000 @@ -1851,26 +1851,25 @@ static PyObject * builtin_reduce(PyObject *self, PyObject *args) { - PyObject *seq, *func, *result = NULL; - PySequenceMethods *sqf; - register int i; + PyObject *seq, *func, *result = NULL, *it; if (!PyArg_ParseTuple(args, "OO|O:reduce", &func, &seq, &result)) return NULL; if (result != NULL) Py_INCREF(result); - sqf = seq->ob_type->tp_as_sequence; - if (sqf == NULL || sqf->sq_item == NULL) { + it = PyObject_GetIter(seq); + if (it == NULL) { PyErr_SetString(PyExc_TypeError, - "reduce() arg 2 must be a sequence"); + "reduce() arg 2 must support iteration"); + Py_XDECREF(result); return NULL; } if ((args = PyTuple_New(2)) == NULL) goto Fail; - for (i = 0; ; ++i) { + for (;;) { PyObject *op2; if (args->ob_refcnt > 1) { @@ -1879,12 +1878,18 @@ goto Fail; } - if ((op2 = (*sqf->sq_item)(seq, i)) == NULL) { - if (PyErr_ExceptionMatches(PyExc_IndexError)) { - PyErr_Clear(); - break; + op2 = PyIter_Next(it); + if (op2 == NULL) { + /* StopIteration is *implied* by a NULL return from + * PyIter_Next() if PyErr_Occurred() is false. + */ + if (PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_StopIteration)) + PyErr_Clear(); + else + goto Fail; } - goto Fail; + break; } if (result == NULL) @@ -1903,11 +1908,13 @@ PyErr_SetString(PyExc_TypeError, "reduce() of empty sequence with no initial value"); + Py_DECREF(it); return result; Fail: Py_XDECREF(args); Py_XDECREF(result); + Py_DECREF(it); return NULL; }
