Commit 0df97d1c authored by Raymond Hettinger's avatar Raymond Hettinger

Added optional None arguments to itertools.islice().

parent 5f70d29f
...@@ -261,6 +261,11 @@ by functions or loops that truncate the stream. ...@@ -261,6 +261,11 @@ by functions or loops that truncate the stream.
yield element yield element
next += step next += step
\end{verbatim} \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} \end{funcdesc}
\begin{funcdesc}{izip}{*iterables} \begin{funcdesc}{izip}{*iterables}
......
...@@ -260,6 +260,8 @@ class TestBasicOps(unittest.TestCase): ...@@ -260,6 +260,8 @@ class TestBasicOps(unittest.TestCase):
# Test stop=None # Test stop=None
self.assertEqual(list(islice(xrange(10), None)), range(10)) 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), 2, None)), range(2, 10))
self.assertEqual(list(islice(xrange(10), 1, None, 2)), range(1, 10, 2)) self.assertEqual(list(islice(xrange(10), 1, None, 2)), range(1, 10, 2))
......
...@@ -17,6 +17,10 @@ Core and builtins ...@@ -17,6 +17,10 @@ Core and builtins
Extension Modules 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 Library
------- -------
......
...@@ -1044,14 +1044,14 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -1044,14 +1044,14 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
PyObject *seq; PyObject *seq;
long start=0, stop=-1, step=1; long start=0, stop=-1, step=1;
PyObject *it, *a1=NULL, *a2=NULL; PyObject *it, *a1=NULL, *a2=NULL, *a3=NULL;
int numargs; int numargs;
isliceobject *lz; isliceobject *lz;
numargs = PyTuple_Size(args); if (!PyArg_UnpackTuple(args, "islice", 2, 4, &seq, &a1, &a2, &a3))
if (!PyArg_ParseTuple(args, "OO|Ol:islice", &seq, &a1, &a2, &step))
return NULL; return NULL;
numargs = PyTuple_Size(args);
if (numargs == 2) { if (numargs == 2) {
if (a1 != Py_None) { if (a1 != Py_None) {
stop = PyInt_AsLong(a1); stop = PyInt_AsLong(a1);
...@@ -1059,39 +1059,41 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -1059,39 +1059,41 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (PyErr_Occurred()) if (PyErr_Occurred())
PyErr_Clear(); PyErr_Clear();
PyErr_SetString(PyExc_ValueError, 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; return NULL;
} }
} }
} else { } else {
start = PyInt_AsLong(a1); if (a1 != Py_None)
if (start == -1 && PyErr_Occurred()) { start = PyInt_AsLong(a1);
if (start == -1 && PyErr_Occurred())
PyErr_Clear(); PyErr_Clear();
PyErr_SetString(PyExc_ValueError,
"Start argument must be a non-negative integer.");
return NULL;
}
if (a2 != Py_None) { if (a2 != Py_None) {
stop = PyInt_AsLong(a2); stop = PyInt_AsLong(a2);
if (stop == -1) { if (stop == -1) {
if (PyErr_Occurred()) if (PyErr_Occurred())
PyErr_Clear(); PyErr_Clear();
PyErr_SetString(PyExc_ValueError, 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; return NULL;
} }
} }
} }
if (start<0 || stop<-1) { if (start<0 || stop<-1) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"Indices for islice() must be non-negative integers."); "Indices for islice() must be non-negative integers or None.");
return NULL; return NULL;
} }
if (a3 != NULL) {
if (a3 != Py_None)
step = PyInt_AsLong(a3);
if (step == -1 && PyErr_Occurred())
PyErr_Clear();
}
if (step<1) { if (step<1) {
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
"Step must be one or larger for islice()."); "Step for islice() must be a positive integer or None.");
return NULL; return NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment