[Python-checkins] r65615 - in python/trunk: Lib/functools.py Lib/test/test_functools.py Misc/NEWS Modules/_functoolsmodule.c
brett.cannon
python-checkins at python.org
Sun Aug 10 01:30:55 CEST 2008
Author: brett.cannon
Date: Sun Aug 10 01:30:55 2008
New Revision: 65615
Log:
Copy reduce() to _functools so to have functools.reduce() not raise a warning
from usage under -3.
Modified:
python/trunk/Lib/functools.py
python/trunk/Lib/test/test_functools.py
python/trunk/Misc/NEWS
python/trunk/Modules/_functoolsmodule.c
Modified: python/trunk/Lib/functools.py
==============================================================================
--- python/trunk/Lib/functools.py (original)
+++ python/trunk/Lib/functools.py Sun Aug 10 01:30:55 2008
@@ -7,8 +7,7 @@
# Copyright (C) 2006 Python Software Foundation.
# See C source code for _functools credits/copyright
-from _functools import partial
-from __builtin__ import reduce
+from _functools import partial, reduce
# update_wrapper() and wraps() are tools to help write
# wrapper functions that can handle naive introspection
Modified: python/trunk/Lib/test/test_functools.py
==============================================================================
--- python/trunk/Lib/test/test_functools.py (original)
+++ python/trunk/Lib/test/test_functools.py Sun Aug 10 01:30:55 2008
@@ -267,6 +267,48 @@
self.assertEqual(wrapper.dict_attr, f.dict_attr)
+class TestReduce(unittest.TestCase):
+
+ def test_reduce(self):
+ class Squares:
+
+ def __init__(self, max):
+ self.max = max
+ self.sofar = []
+
+ def __len__(self): return len(self.sofar)
+
+ def __getitem__(self, i):
+ if not 0 <= i < self.max: raise IndexError
+ n = len(self.sofar)
+ while n <= i:
+ self.sofar.append(n*n)
+ n += 1
+ return self.sofar[i]
+
+ reduce = functools.reduce
+ self.assertEqual(reduce(lambda x, y: x+y, ['a', 'b', 'c'], ''), 'abc')
+ self.assertEqual(
+ reduce(lambda x, y: x+y, [['a', 'c'], [], ['d', 'w']], []),
+ ['a','c','d','w']
+ )
+ self.assertEqual(reduce(lambda x, y: x*y, range(2,8), 1), 5040)
+ self.assertEqual(
+ reduce(lambda x, y: x*y, range(2,21), 1L),
+ 2432902008176640000L
+ )
+ self.assertEqual(reduce(lambda x, y: x+y, Squares(10)), 285)
+ self.assertEqual(reduce(lambda x, y: x+y, Squares(10), 0), 285)
+ self.assertEqual(reduce(lambda x, y: x+y, Squares(0), 0), 0)
+ self.assertRaises(TypeError, reduce)
+ self.assertRaises(TypeError, reduce, 42, 42)
+ self.assertRaises(TypeError, reduce, 42, 42, 42)
+ self.assertEqual(reduce(42, "1"), "1") # func is never called with one item
+ self.assertEqual(reduce(42, "", "1"), "1") # func is never called with one item
+ self.assertRaises(TypeError, reduce, 42, (42, 42))
+
+
+
def test_main(verbose=None):
import sys
@@ -275,7 +317,8 @@
TestPartialSubclass,
TestPythonPartial,
TestUpdateWrapper,
- TestWraps
+ TestWraps,
+ TestReduce,
)
test_support.run_unittest(*test_classes)
Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS (original)
+++ python/trunk/Misc/NEWS Sun Aug 10 01:30:55 2008
@@ -41,6 +41,9 @@
Library
-------
+- Copied the implementation of reduce() to _functools.reduce() to have a
+ version that did not raise a DeprecationWarning under -3.
+
- Issue #3205: When iterating over a BZ2File fails allocating memory, raise
a MemoryError rather than silently stop the iteration.
Modified: python/trunk/Modules/_functoolsmodule.c
==============================================================================
--- python/trunk/Modules/_functoolsmodule.c (original)
+++ python/trunk/Modules/_functoolsmodule.c Sun Aug 10 01:30:55 2008
@@ -9,6 +9,84 @@
All rights reserved.
*/
+/* reduce() *************************************************************/
+
+static PyObject *
+functools_reduce(PyObject *self, PyObject *args)
+{
+ PyObject *seq, *func, *result = NULL, *it;
+
+ if (!PyArg_UnpackTuple(args, "reduce", 2, 3, &func, &seq, &result))
+ return NULL;
+ if (result != NULL)
+ Py_INCREF(result);
+
+ it = PyObject_GetIter(seq);
+ if (it == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "reduce() arg 2 must support iteration");
+ Py_XDECREF(result);
+ return NULL;
+ }
+
+ if ((args = PyTuple_New(2)) == NULL)
+ goto Fail;
+
+ for (;;) {
+ PyObject *op2;
+
+ if (args->ob_refcnt > 1) {
+ Py_DECREF(args);
+ if ((args = PyTuple_New(2)) == NULL)
+ goto Fail;
+ }
+
+ op2 = PyIter_Next(it);
+ if (op2 == NULL) {
+ if (PyErr_Occurred())
+ goto Fail;
+ break;
+ }
+
+ if (result == NULL)
+ result = op2;
+ else {
+ PyTuple_SetItem(args, 0, result);
+ PyTuple_SetItem(args, 1, op2);
+ if ((result = PyEval_CallObject(func, args)) == NULL)
+ goto Fail;
+ }
+ }
+
+ Py_DECREF(args);
+
+ if (result == NULL)
+ 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;
+}
+
+PyDoc_STRVAR(reduce_doc,
+"reduce(function, sequence[, initial]) -> value\n\
+\n\
+Apply a function of two arguments cumulatively to the items of a sequence,\n\
+from left to right, so as to reduce the sequence to a single value.\n\
+For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates\n\
+((((1+2)+3)+4)+5). If initial is present, it is placed before the items\n\
+of the sequence in the calculation, and serves as a default when the\n\
+sequence is empty.");
+
+
+
+
/* partial object **********************************************************/
typedef struct {
@@ -247,6 +325,7 @@
"Tools that operate on functions.");
static PyMethodDef module_methods[] = {
+ {"reduce", functools_reduce, METH_VARARGS, reduce_doc},
{NULL, NULL} /* sentinel */
};
More information about the Python-checkins
mailing list