Skip to content

Commit a70b191

Browse files
committed
Adding new built-in function sum, with docs and tests.
1 parent 060641d commit a70b191

5 files changed

Lines changed: 98 additions & 1 deletion

File tree

Doc/lib/libfuncs.tex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,14 @@ \section{Built-in Functions \label{built-in-funcs}}
897897
\versionadded{2.2}
898898
\end{funcdesc}
899899

900+
\begin{funcdesc}{sum}{sequence\optional{start=0}}
901+
Sums up the items of a \var{sequence}, from left to right, and returns
902+
the total. The \var{sequence}'s items are normally numbers, and are
903+
not allowed to be strings. The fast, correct way to join up a
904+
sequence of strings is by calling \code{''.join(\var{sequence})}.
905+
\versionadded{2.3}
906+
\end{funcdesc}
907+
900908
\begin{funcdesc}{super}{type\optional{object-or-type}}
901909
Return the superclass of \var{type}. If the second argument is omitted
902910
the super object returned is unbound. If the second argument is an

Doc/tut/tut.tex

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1819,6 +1819,9 @@ \subsection{Functional Programming Tools \label{functional}}
18191819
0
18201820
\end{verbatim}
18211821

1822+
Don't use this example's definition of \code{sum}: since summing numbers
1823+
is such a common need, a built-in function \code{sum(\var{sequence})} is
1824+
already provided, and works exactly like this\versionadded{2,3}.
18221825

18231826
\subsection{List Comprehensions}
18241827

@@ -2502,7 +2505,7 @@ \section{The \function{dir()} Function \label{dir}}
25022505
'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'min',
25032506
'object', 'oct', 'open', 'ord', 'pow', 'property', 'quit',
25042507
'range', 'raw_input', 'reduce', 'reload', 'repr', 'round',
2505-
'setattr', 'slice', 'staticmethod', 'str', 'string', 'super',
2508+
'setattr', 'slice', 'staticmethod', 'str', 'string', 'sum', 'super',
25062509
'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
25072510
\end{verbatim}
25082511

Lib/test/test_builtin.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,6 +1099,27 @@ def test_str(self):
10991099
a[0] = a
11001100
self.assertEqual(str(a), '{0: {...}}')
11011101

1102+
def test_sum(self):
1103+
self.assertEqual(sum([]), 0)
1104+
self.assertEqual(sum(range(2,8)), 27)
1105+
self.assertEqual(sum(iter(range(2,8))), 27)
1106+
self.assertEqual(sum(Squares(10)), 285)
1107+
self.assertEqual(sum(iter(Squares(10))), 285)
1108+
self.assertEqual(sum([[1], [2], [3]], []), [1, 2, 3])
1109+
1110+
self.assertRaises(TypeError, sum)
1111+
self.assertRaises(TypeError, sum, 42)
1112+
self.assertRaises(TypeError, sum, ['a', 'b', 'c'])
1113+
self.assertRaises(TypeError, sum, ['a', 'b', 'c'], '')
1114+
self.assertRaises(TypeError, sum, [[1], [2], [3]])
1115+
self.assertRaises(TypeError, sum, [{2:3}])
1116+
self.assertRaises(TypeError, sum, [{2:3}]*2, {2:3})
1117+
1118+
class BadSeq:
1119+
def __getitem__(self, index):
1120+
raise ValueError
1121+
self.assertRaises(ValueError, sum, BadSeq())
1122+
11021123
def test_tuple(self):
11031124
self.assertEqual(tuple(()), ())
11041125
t0_3 = (0, 1, 2, 3)

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ What's New in Python 2.3 beta 1?
1212
Core and builtins
1313
-----------------
1414

15+
- New builtin function sum(seq, start=0) returns the sum of all the
16+
items in iterable object seq, plus start (items are normally numbers,
17+
and cannot be strings).
18+
1519
- bool() called without arguments now returns False rather than
1620
raising an exception. This is consistent with calling the
1721
constructors for the other builtin types -- called without argument

Python/bltinmodule.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,6 +1798,66 @@ PyDoc_STRVAR(vars_doc,
17981798
Without arguments, equivalent to locals().\n\
17991799
With an argument, equivalent to object.__dict__.");
18001800

1801+
1802+
static PyObject*
1803+
builtin_sum(PyObject *self, PyObject *args)
1804+
{
1805+
PyObject *seq;
1806+
PyObject *result = NULL;
1807+
PyObject *temp, *item, *iter;
1808+
1809+
if (!PyArg_ParseTuple(args, "O|O:sum", &seq, &result))
1810+
return NULL;
1811+
1812+
iter = PyObject_GetIter(seq);
1813+
if (iter == NULL)
1814+
return NULL;
1815+
1816+
if (result == NULL) {
1817+
result = PyInt_FromLong(0);
1818+
if (result == NULL) {
1819+
Py_DECREF(iter);
1820+
return NULL;
1821+
}
1822+
} else {
1823+
/* reject string values for 'start' parameter */
1824+
if (PyObject_TypeCheck(result, &PyBaseString_Type)) {
1825+
PyErr_SetString(PyExc_TypeError,
1826+
"can't sum strings [use ''.join(seq) instead]");
1827+
Py_DECREF(result);
1828+
Py_DECREF(iter);
1829+
return NULL;
1830+
}
1831+
}
1832+
1833+
for(;;) {
1834+
item = PyIter_Next(iter);
1835+
if (item == NULL) {
1836+
/* error, or end-of-sequence */
1837+
if (PyErr_Occurred()) {
1838+
Py_DECREF(result);
1839+
result = NULL;
1840+
}
1841+
break;
1842+
}
1843+
temp = PyNumber_Add(result, item);
1844+
Py_DECREF(result);
1845+
Py_DECREF(item);
1846+
result = temp;
1847+
if (result == NULL)
1848+
break;
1849+
}
1850+
Py_DECREF(iter);
1851+
return result;
1852+
}
1853+
1854+
PyDoc_STRVAR(sum_doc,
1855+
"sum(sequence, start=0) -> value\n\
1856+
\n\
1857+
Returns the sum of a sequence of numbers (NOT strings) plus the value\n\
1858+
of parameter 'start'. When the sequence is empty, returns start.");
1859+
1860+
18011861
static PyObject *
18021862
builtin_isinstance(PyObject *self, PyObject *args)
18031863
{
@@ -2001,6 +2061,7 @@ static PyMethodDef builtin_methods[] = {
20012061
{"repr", builtin_repr, METH_O, repr_doc},
20022062
{"round", builtin_round, METH_VARARGS, round_doc},
20032063
{"setattr", builtin_setattr, METH_VARARGS, setattr_doc},
2064+
{"sum", builtin_sum, METH_VARARGS, sum_doc},
20042065
#ifdef Py_USING_UNICODE
20052066
{"unichr", builtin_unichr, METH_VARARGS, unichr_doc},
20062067
#endif

0 commit comments

Comments
 (0)