Adding new built-in function sum, with docs and tests.

This commit is contained in:
Alex Martelli 2003-04-22 08:12:33 +00:00
parent 060641d511
commit a70b19147f
5 changed files with 98 additions and 1 deletions

View file

@ -897,6 +897,14 @@ class C:
\versionadded{2.2} \versionadded{2.2}
\end{funcdesc} \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}} \begin{funcdesc}{super}{type\optional{object-or-type}}
Return the superclass of \var{type}. If the second argument is omitted Return the superclass of \var{type}. If the second argument is omitted
the super object returned is unbound. If the second argument is an the super object returned is unbound. If the second argument is an

View file

@ -1819,6 +1819,9 @@ item, then to the result and the next item, and so on. For example,
0 0
\end{verbatim} \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} \subsection{List Comprehensions}
@ -2502,7 +2505,7 @@ standard module \module{__builtin__}\refbimodindex{__builtin__}:
'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'min', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'min',
'object', 'oct', 'open', 'ord', 'pow', 'property', 'quit', 'object', 'oct', 'open', 'ord', 'pow', 'property', 'quit',
'range', 'raw_input', 'reduce', 'reload', 'repr', 'round', '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'] 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip']
\end{verbatim} \end{verbatim}

View file

@ -1099,6 +1099,27 @@ class BuiltinTest(unittest.TestCase):
a[0] = a a[0] = a
self.assertEqual(str(a), '{0: {...}}') 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): def test_tuple(self):
self.assertEqual(tuple(()), ()) self.assertEqual(tuple(()), ())
t0_3 = (0, 1, 2, 3) t0_3 = (0, 1, 2, 3)

View file

@ -12,6 +12,10 @@ What's New in Python 2.3 beta 1?
Core and builtins 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 - bool() called without arguments now returns False rather than
raising an exception. This is consistent with calling the raising an exception. This is consistent with calling the
constructors for the other builtin types -- called without argument constructors for the other builtin types -- called without argument

View file

@ -1798,6 +1798,66 @@ PyDoc_STRVAR(vars_doc,
Without arguments, equivalent to locals().\n\ Without arguments, equivalent to locals().\n\
With an argument, equivalent to object.__dict__."); 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 * static PyObject *
builtin_isinstance(PyObject *self, PyObject *args) builtin_isinstance(PyObject *self, PyObject *args)
{ {
@ -2001,6 +2061,7 @@ static PyMethodDef builtin_methods[] = {
{"repr", builtin_repr, METH_O, repr_doc}, {"repr", builtin_repr, METH_O, repr_doc},
{"round", builtin_round, METH_VARARGS, round_doc}, {"round", builtin_round, METH_VARARGS, round_doc},
{"setattr", builtin_setattr, METH_VARARGS, setattr_doc}, {"setattr", builtin_setattr, METH_VARARGS, setattr_doc},
{"sum", builtin_sum, METH_VARARGS, sum_doc},
#ifdef Py_USING_UNICODE #ifdef Py_USING_UNICODE
{"unichr", builtin_unichr, METH_VARARGS, unichr_doc}, {"unichr", builtin_unichr, METH_VARARGS, unichr_doc},
#endif #endif