diff options
-rw-r--r-- | Doc/lib/libitertools.tex | 5 | ||||
-rw-r--r-- | Lib/test/test_itertools.py | 2 | ||||
-rw-r--r-- | Misc/NEWS | 4 | ||||
-rw-r--r-- | Modules/itertoolsmodule.c | 30 |
4 files changed, 27 insertions, 14 deletions
diff --git a/Doc/lib/libitertools.tex b/Doc/lib/libitertools.tex index be53015..fbde69d 100644 --- a/Doc/lib/libitertools.tex +++ b/Doc/lib/libitertools.tex @@ -261,6 +261,11 @@ by functions or loops that truncate the stream. yield element next += step \end{verbatim} + + If \var{start} is \code{None}, then iteration starts at zero. + If \var{step} is \code{None}, then the step defaults to one. + \versionchanged[accept \code{None} values for default \var{start} and + \var{step}]{2.5} \end{funcdesc} \begin{funcdesc}{izip}{*iterables} diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index 0f74c62..becb3b2 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -260,6 +260,8 @@ class TestBasicOps(unittest.TestCase): # Test stop=None self.assertEqual(list(islice(xrange(10), None)), range(10)) + self.assertEqual(list(islice(xrange(10), None, None)), range(10)) + self.assertEqual(list(islice(xrange(10), None, None, None)), range(10)) self.assertEqual(list(islice(xrange(10), 2, None)), range(2, 10)) self.assertEqual(list(islice(xrange(10), 1, None, 2)), range(1, 10, 2)) @@ -17,6 +17,10 @@ Core and builtins Extension Modules ----------------- +- itertools.islice() now accepts None for the start and step arguments. + This allows islice() to work more readily with slices: + islice(s.start, s.stop, s.step) + Library ------- diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index bf148ac..31ba13a 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -1044,14 +1044,14 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *seq; long start=0, stop=-1, step=1; - PyObject *it, *a1=NULL, *a2=NULL; + PyObject *it, *a1=NULL, *a2=NULL, *a3=NULL; int numargs; isliceobject *lz; - numargs = PyTuple_Size(args); - if (!PyArg_ParseTuple(args, "OO|Ol:islice", &seq, &a1, &a2, &step)) + if (!PyArg_UnpackTuple(args, "islice", 2, 4, &seq, &a1, &a2, &a3)) return NULL; + numargs = PyTuple_Size(args); if (numargs == 2) { if (a1 != Py_None) { stop = PyInt_AsLong(a1); @@ -1059,39 +1059,41 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) if (PyErr_Occurred()) PyErr_Clear(); PyErr_SetString(PyExc_ValueError, - "Stop argument must be a non-negative integer or None."); + "Stop argument for islice() must be a non-negative integer or None."); return NULL; } } } else { - start = PyInt_AsLong(a1); - if (start == -1 && PyErr_Occurred()) { + if (a1 != Py_None) + start = PyInt_AsLong(a1); + if (start == -1 && PyErr_Occurred()) PyErr_Clear(); - PyErr_SetString(PyExc_ValueError, - "Start argument must be a non-negative integer."); - return NULL; - } if (a2 != Py_None) { stop = PyInt_AsLong(a2); if (stop == -1) { if (PyErr_Occurred()) PyErr_Clear(); PyErr_SetString(PyExc_ValueError, - "Stop argument must be a non-negative integer or None."); + "Stop argument for islice() must be a non-negative integer or None."); return NULL; } } } - if (start<0 || stop<-1) { PyErr_SetString(PyExc_ValueError, - "Indices for islice() must be non-negative integers."); + "Indices for islice() must be non-negative integers or None."); return NULL; } + if (a3 != NULL) { + if (a3 != Py_None) + step = PyInt_AsLong(a3); + if (step == -1 && PyErr_Occurred()) + PyErr_Clear(); + } if (step<1) { PyErr_SetString(PyExc_ValueError, - "Step must be one or larger for islice()."); + "Step for islice() must be a positive integer or None."); return NULL; } |