#2831: add start argument to enumerate(). Patch by Scott Dial and me.
This commit is contained in:
parent
ef9764f1a4
commit
913835763a
|
@ -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]])
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue