mirror of
https://github.com/python/cpython.git
synced 2025-10-17 12:18:23 +00:00
Generalize reduce() to work with iterators.
NEEDS DOC CHANGES.
This commit is contained in:
parent
8bc10b0c57
commit
15d81efb8a
3 changed files with 33 additions and 12 deletions
|
@ -385,4 +385,17 @@ class TestCase(unittest.TestCase):
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Test reduces()'s use of iterators.
|
||||||
|
def test_builtin_reduce(self):
|
||||||
|
from operator import add
|
||||||
|
self.assertEqual(reduce(add, SequenceClass(5)), 10)
|
||||||
|
self.assertEqual(reduce(add, SequenceClass(5), 42), 52)
|
||||||
|
self.assertRaises(TypeError, reduce, add, SequenceClass(0))
|
||||||
|
self.assertEqual(reduce(add, SequenceClass(0), 42), 42)
|
||||||
|
self.assertEqual(reduce(add, SequenceClass(1)), 0)
|
||||||
|
self.assertEqual(reduce(add, SequenceClass(1), 42), 42)
|
||||||
|
|
||||||
|
d = {"one": 1, "two": 2, "three": 3}
|
||||||
|
self.assertEqual(reduce(add, d), "".join(d.keys()))
|
||||||
|
|
||||||
run_unittest(TestCase)
|
run_unittest(TestCase)
|
||||||
|
|
|
@ -22,6 +22,7 @@ Core
|
||||||
map()
|
map()
|
||||||
max()
|
max()
|
||||||
min()
|
min()
|
||||||
|
reduce()
|
||||||
|
|
||||||
|
|
||||||
What's New in Python 2.1 (final)?
|
What's New in Python 2.1 (final)?
|
||||||
|
|
|
@ -1851,26 +1851,25 @@ is printed without a trailing newline before reading.";
|
||||||
static PyObject *
|
static PyObject *
|
||||||
builtin_reduce(PyObject *self, PyObject *args)
|
builtin_reduce(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyObject *seq, *func, *result = NULL;
|
PyObject *seq, *func, *result = NULL, *it;
|
||||||
PySequenceMethods *sqf;
|
|
||||||
register int i;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "OO|O:reduce", &func, &seq, &result))
|
if (!PyArg_ParseTuple(args, "OO|O:reduce", &func, &seq, &result))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (result != NULL)
|
if (result != NULL)
|
||||||
Py_INCREF(result);
|
Py_INCREF(result);
|
||||||
|
|
||||||
sqf = seq->ob_type->tp_as_sequence;
|
it = PyObject_GetIter(seq);
|
||||||
if (sqf == NULL || sqf->sq_item == NULL) {
|
if (it == NULL) {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"reduce() arg 2 must be a sequence");
|
"reduce() arg 2 must support iteration");
|
||||||
|
Py_XDECREF(result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((args = PyTuple_New(2)) == NULL)
|
if ((args = PyTuple_New(2)) == NULL)
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
for (i = 0; ; ++i) {
|
for (;;) {
|
||||||
PyObject *op2;
|
PyObject *op2;
|
||||||
|
|
||||||
if (args->ob_refcnt > 1) {
|
if (args->ob_refcnt > 1) {
|
||||||
|
@ -1879,12 +1878,18 @@ builtin_reduce(PyObject *self, PyObject *args)
|
||||||
goto Fail;
|
goto Fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((op2 = (*sqf->sq_item)(seq, i)) == NULL) {
|
op2 = PyIter_Next(it);
|
||||||
if (PyErr_ExceptionMatches(PyExc_IndexError)) {
|
if (op2 == NULL) {
|
||||||
PyErr_Clear();
|
/* StopIteration is *implied* by a NULL return from
|
||||||
break;
|
* 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)
|
if (result == NULL)
|
||||||
|
@ -1903,11 +1908,13 @@ builtin_reduce(PyObject *self, PyObject *args)
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"reduce() of empty sequence with no initial value");
|
"reduce() of empty sequence with no initial value");
|
||||||
|
|
||||||
|
Py_DECREF(it);
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
Fail:
|
Fail:
|
||||||
Py_XDECREF(args);
|
Py_XDECREF(args);
|
||||||
Py_XDECREF(result);
|
Py_XDECREF(result);
|
||||||
|
Py_DECREF(it);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue