]> granicus.if.org Git - python/commitdiff
#2831: add start argument to enumerate(). Patch by Scott Dial and me.
authorGeorg Brandl <georg@python.org>
Tue, 13 May 2008 19:04:54 +0000 (19:04 +0000)
committerGeorg Brandl <georg@python.org>
Tue, 13 May 2008 19:04:54 +0000 (19:04 +0000)
Doc/library/functions.rst
Lib/test/test_enumerate.py
Objects/enumobject.c

index bc07d84b02d49eb12c987042dfb3af190f9f405d..6de9392259ecfbc001fc9c6c7bcaf5cbd9912ba7 100644 (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]])
index e0a272e025f9aea2e9928197f6bd34affa18b3b9..a27846fbcf0229d597461686365b69a1825a2f8c 100644 (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)
index 230dba294d58a17ae819bb2ac763cbc70b0cb2b4..0bacc8346c3a3e58f05881c1a04f9d4bf91cb157 100644 (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;
+       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;