summaryrefslogtreecommitdiffstats
path: root/Python/bltinmodule.c
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-05-04 04:39:21 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-05-04 04:39:21 (GMT)
commit15d81efb8a7045ce2860792f11741965b496a98b (patch)
treed9fffce067670c536175ebd8f6b81fc9b20976a3 /Python/bltinmodule.c
parent8bc10b0c579f740bbdf77a1db90d5de733fcf20e (diff)
downloadcpython-15d81efb8a7045ce2860792f11741965b496a98b.zip
cpython-15d81efb8a7045ce2860792f11741965b496a98b.tar.gz
cpython-15d81efb8a7045ce2860792f11741965b496a98b.tar.bz2
Generalize reduce() to work with iterators.
NEEDS DOC CHANGES.
Diffstat (limited to 'Python/bltinmodule.c')
-rw-r--r--Python/bltinmodule.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 0c20d10..5209607 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1851,26 +1851,25 @@ is printed without a trailing newline before reading.";
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 @@ builtin_reduce(PyObject *self, PyObject *args)
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 @@ builtin_reduce(PyObject *self, PyObject *args)
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;
}