Added optional None arguments to itertools.islice().

This commit is contained in:
Raymond Hettinger 2004-12-05 09:25:51 +00:00
parent d2f70cbe8e
commit b2594050ea
4 changed files with 27 additions and 14 deletions

View file

@ -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}

View file

@ -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))

View file

@ -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
------- -------

View file

@ -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)
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 {
if (a1 != Py_None)
start = PyInt_AsLong(a1); start = PyInt_AsLong(a1);
if (start == -1 && PyErr_Occurred()) { 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;
} }