#2831: add start argument to enumerate(). Patch by Scott Dial and me.

This commit is contained in:
Georg Brandl 2008-05-13 19:04:54 +00:00
parent ef9764f1a4
commit 913835763a
3 changed files with 45 additions and 11 deletions

View File

@ -335,15 +335,15 @@ available. They are listed here in alphabetical order.
Using :func:`divmod` with complex numbers is deprecated.
.. function:: enumerate(sequence)
.. function:: enumerate(sequence[, start=0])
Return an enumerate object. *sequence* must be a sequence, an
:term:`iterator`, or some other object which supports iteration. The
:meth:`next` method of the iterator returned by :func:`enumerate` returns a
tuple containing a count (from zero) and the corresponding value obtained
from iterating over *iterable*. :func:`enumerate` is useful for obtaining an
indexed series: ``(0, seq[0])``, ``(1, seq[1])``, ``(2, seq[2])``, .... For
example:
tuple containing a count (from *start* which defaults to 0) and the
corresponding value obtained from iterating over *iterable*.
:func:`enumerate` is useful for obtaining an indexed series: ``(0, seq[0])``,
``(1, seq[1])``, ``(2, seq[2])``, .... For example:
>>> for i, season in enumerate(['Spring', 'Summer', 'Fall', 'Winter']):
... print i, season
@ -353,6 +353,8 @@ available. They are listed here in alphabetical order.
3 Winter
.. versionadded:: 2.3
.. versionadded:: 2.6
The *start* parameter.
.. function:: eval(expression[, globals[, locals]])

View File

@ -100,7 +100,8 @@ class EnumerateTestCase(unittest.TestCase):
def test_argumentcheck(self):
self.assertRaises(TypeError, self.enum) # no arguments
self.assertRaises(TypeError, self.enum, 1) # wrong type (not iterable)
self.assertRaises(TypeError, self.enum, 'abc', 2) # too many arguments
self.assertRaises(TypeError, self.enum, 'abc', 'a') # wrong type
self.assertRaises(TypeError, self.enum, 'abc', 2, 3) # too many arguments
def test_tuple_reuse(self):
# Tests an implementation detail where tuple is reused
@ -196,6 +197,19 @@ class TestReversed(unittest.TestCase):
self.assertEqual(rc, sys.getrefcount(r))
class TestStart(EnumerateTestCase):
enum = lambda i: enumerate(i, start=11)
seq, res = 'abc', [(1, 'a'), (2, 'b'), (3, 'c')]
class TestLongStart(EnumerateTestCase):
enum = lambda i: enumerate(i, start=sys.maxint+1)
seq, res = 'abc', [(sys.maxint+1,'a'), (sys.maxint+2,'b'),
(sys.maxint+3,'c')]
def test_main(verbose=None):
testclasses = (EnumerateTestCase, SubclassTestCase, TestEmpty, TestBig,
TestReversed)

View File

@ -15,18 +15,36 @@ enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
enumobject *en;
PyObject *seq = NULL;
static char *kwlist[] = {"sequence", 0};
PyObject *start = NULL;
static char *kwlist[] = {"sequence", "start", 0};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:enumerate", kwlist,
&seq))
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:enumerate", kwlist,
&seq, &start))
return NULL;
en = (enumobject *)type->tp_alloc(type, 0);
if (en == NULL)
return NULL;
en->en_index = 0;
en->en_sit = PyObject_GetIter(seq);
if (start) {
start = PyNumber_Index(start);
if (start == NULL) {
Py_DECREF(en);
return NULL;
}
if (PyLong_Check(start)) {
en->en_index = LONG_MAX;
en->en_longindex = start;
} else {
assert(PyInt_Check(start));
en->en_index = PyInt_AsLong(start);
en->en_longindex = NULL;
Py_DECREF(start);
}
} else {
en->en_index = 0;
en->en_longindex = NULL;
}
en->en_sit = PyObject_GetIter(seq);
if (en->en_sit == NULL) {
Py_DECREF(en);
return NULL;