summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2008-05-13 19:04:54 (GMT)
committerGeorg Brandl <georg@python.org>2008-05-13 19:04:54 (GMT)
commit913835763a4734097423c49e284ce8d4b1093917 (patch)
tree500df9f02e13104b9c00d9f07541ab324abc1a29
parentef9764f1a479808b340c16bcfdb0cd6838465ea9 (diff)
downloadcpython-913835763a4734097423c49e284ce8d4b1093917.zip
cpython-913835763a4734097423c49e284ce8d4b1093917.tar.gz
cpython-913835763a4734097423c49e284ce8d4b1093917.tar.bz2
#2831: add start argument to enumerate(). Patch by Scott Dial and me.
-rw-r--r--Doc/library/functions.rst12
-rw-r--r--Lib/test/test_enumerate.py16
-rw-r--r--Objects/enumobject.c28
3 files changed, 45 insertions, 11 deletions
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index bc07d84..6de9392 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -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]])
diff --git a/Lib/test/test_enumerate.py b/Lib/test/test_enumerate.py
index e0a272e..a27846f 100644
--- a/Lib/test/test_enumerate.py
+++ b/Lib/test/test_enumerate.py
@@ -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)
diff --git a/Objects/enumobject.c b/Objects/enumobject.c
index 230dba2..0bacc83 100644
--- a/Objects/enumobject.c
+++ b/Objects/enumobject.c
@@ -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;
+ 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);
- en->en_longindex = NULL;
if (en->en_sit == NULL) {
Py_DECREF(en);
return NULL;