summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Martelli <aleaxit@gmail.com>2003-04-22 08:12:33 (GMT)
committerAlex Martelli <aleaxit@gmail.com>2003-04-22 08:12:33 (GMT)
commita70b19147fd163744be34745d393af7be603629f (patch)
tree8ec1a2ae14cfae5fb3a3f14af05a9c9f60b3d739
parent060641d51160f6bf49a049bb677f8412b5a19de3 (diff)
downloadcpython-a70b19147fd163744be34745d393af7be603629f.zip
cpython-a70b19147fd163744be34745d393af7be603629f.tar.gz
cpython-a70b19147fd163744be34745d393af7be603629f.tar.bz2
Adding new built-in function sum, with docs and tests.
-rw-r--r--Doc/lib/libfuncs.tex8
-rw-r--r--Doc/tut/tut.tex5
-rw-r--r--Lib/test/test_builtin.py21
-rw-r--r--Misc/NEWS4
-rw-r--r--Python/bltinmodule.c61
5 files changed, 98 insertions, 1 deletions
diff --git a/Doc/lib/libfuncs.tex b/Doc/lib/libfuncs.tex
index 323a516..50f22f8 100644
--- a/Doc/lib/libfuncs.tex
+++ b/Doc/lib/libfuncs.tex
@@ -897,6 +897,14 @@ class C:
\versionadded{2.2}
\end{funcdesc}
+\begin{funcdesc}{sum}{sequence\optional{start=0}}
+ Sums up the items of a \var{sequence}, from left to right, and returns
+ the total. The \var{sequence}'s items are normally numbers, and are
+ not allowed to be strings. The fast, correct way to join up a
+ sequence of strings is by calling \code{''.join(\var{sequence})}.
+ \versionadded{2.3}
+\end{funcdesc}
+
\begin{funcdesc}{super}{type\optional{object-or-type}}
Return the superclass of \var{type}. If the second argument is omitted
the super object returned is unbound. If the second argument is an
diff --git a/Doc/tut/tut.tex b/Doc/tut/tut.tex
index 71d3f60..b227576 100644
--- a/Doc/tut/tut.tex
+++ b/Doc/tut/tut.tex
@@ -1819,6 +1819,9 @@ item, then to the result and the next item, and so on. For example,
0
\end{verbatim}
+Don't use this example's definition of \code{sum}: since summing numbers
+is such a common need, a built-in function \code{sum(\var{sequence})} is
+already provided, and works exactly like this\versionadded{2,3}.
\subsection{List Comprehensions}
@@ -2502,7 +2505,7 @@ standard module \module{__builtin__}\refbimodindex{__builtin__}:
'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'min',
'object', 'oct', 'open', 'ord', 'pow', 'property', 'quit',
'range', 'raw_input', 'reduce', 'reload', 'repr', 'round',
- 'setattr', 'slice', 'staticmethod', 'str', 'string', 'super',
+ 'setattr', 'slice', 'staticmethod', 'str', 'string', 'sum', 'super',
'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
\end{verbatim}
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index 3956214..e5c9770 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -1099,6 +1099,27 @@ class BuiltinTest(unittest.TestCase):
a[0] = a
self.assertEqual(str(a), '{0: {...}}')
+ def test_sum(self):
+ self.assertEqual(sum([]), 0)
+ self.assertEqual(sum(range(2,8)), 27)
+ self.assertEqual(sum(iter(range(2,8))), 27)
+ self.assertEqual(sum(Squares(10)), 285)
+ self.assertEqual(sum(iter(Squares(10))), 285)
+ self.assertEqual(sum([[1], [2], [3]], []), [1, 2, 3])
+
+ self.assertRaises(TypeError, sum)
+ self.assertRaises(TypeError, sum, 42)
+ self.assertRaises(TypeError, sum, ['a', 'b', 'c'])
+ self.assertRaises(TypeError, sum, ['a', 'b', 'c'], '')
+ self.assertRaises(TypeError, sum, [[1], [2], [3]])
+ self.assertRaises(TypeError, sum, [{2:3}])
+ self.assertRaises(TypeError, sum, [{2:3}]*2, {2:3})
+
+ class BadSeq:
+ def __getitem__(self, index):
+ raise ValueError
+ self.assertRaises(ValueError, sum, BadSeq())
+
def test_tuple(self):
self.assertEqual(tuple(()), ())
t0_3 = (0, 1, 2, 3)
diff --git a/Misc/NEWS b/Misc/NEWS
index 2897793..330831d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,10 @@ What's New in Python 2.3 beta 1?
Core and builtins
-----------------
+- New builtin function sum(seq, start=0) returns the sum of all the
+ items in iterable object seq, plus start (items are normally numbers,
+ and cannot be strings).
+
- bool() called without arguments now returns False rather than
raising an exception. This is consistent with calling the
constructors for the other builtin types -- called without argument
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index adefba2..0eb8357 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1798,6 +1798,66 @@ PyDoc_STRVAR(vars_doc,
Without arguments, equivalent to locals().\n\
With an argument, equivalent to object.__dict__.");
+
+static PyObject*
+builtin_sum(PyObject *self, PyObject *args)
+{
+ PyObject *seq;
+ PyObject *result = NULL;
+ PyObject *temp, *item, *iter;
+
+ if (!PyArg_ParseTuple(args, "O|O:sum", &seq, &result))
+ return NULL;
+
+ iter = PyObject_GetIter(seq);
+ if (iter == NULL)
+ return NULL;
+
+ if (result == NULL) {
+ result = PyInt_FromLong(0);
+ if (result == NULL) {
+ Py_DECREF(iter);
+ return NULL;
+ }
+ } else {
+ /* reject string values for 'start' parameter */
+ if (PyObject_TypeCheck(result, &PyBaseString_Type)) {
+ PyErr_SetString(PyExc_TypeError,
+ "can't sum strings [use ''.join(seq) instead]");
+ Py_DECREF(result);
+ Py_DECREF(iter);
+ return NULL;
+ }
+ }
+
+ for(;;) {
+ item = PyIter_Next(iter);
+ if (item == NULL) {
+ /* error, or end-of-sequence */
+ if (PyErr_Occurred()) {
+ Py_DECREF(result);
+ result = NULL;
+ }
+ break;
+ }
+ temp = PyNumber_Add(result, item);
+ Py_DECREF(result);
+ Py_DECREF(item);
+ result = temp;
+ if (result == NULL)
+ break;
+ }
+ Py_DECREF(iter);
+ return result;
+}
+
+PyDoc_STRVAR(sum_doc,
+"sum(sequence, start=0) -> value\n\
+\n\
+Returns the sum of a sequence of numbers (NOT strings) plus the value\n\
+of parameter 'start'. When the sequence is empty, returns start.");
+
+
static PyObject *
builtin_isinstance(PyObject *self, PyObject *args)
{
@@ -2001,6 +2061,7 @@ static PyMethodDef builtin_methods[] = {
{"repr", builtin_repr, METH_O, repr_doc},
{"round", builtin_round, METH_VARARGS, round_doc},
{"setattr", builtin_setattr, METH_VARARGS, setattr_doc},
+ {"sum", builtin_sum, METH_VARARGS, sum_doc},
#ifdef Py_USING_UNICODE
{"unichr", builtin_unichr, METH_VARARGS, unichr_doc},
#endif