diff options
-rw-r--r-- | Doc/ref/ref3.tex | 9 | ||||
-rw-r--r-- | Lib/test/test_slice.py | 14 | ||||
-rw-r--r-- | Objects/sliceobject.c | 35 |
3 files changed, 57 insertions, 1 deletions
diff --git a/Doc/ref/ref3.tex b/Doc/ref/ref3.tex index d719db3..9f8d262 100644 --- a/Doc/ref/ref3.tex +++ b/Doc/ref/ref3.tex @@ -892,6 +892,15 @@ Special read-only attributes: \member{start} is the lower bound; \ttindex{stop} \ttindex{step}} +Special method: \method{indices} takes an single integer argument +\var{length} and computes information about the extended slice that +the slice object would describe if applied to a sequence of +\var{length}. It returns a tuple of three integers; respectively +these are the \var{start} and \var{stop} indices and the \var{step} or +stride length of the slice. Missing or out-of-bounds indices are +handled in a manner consistent with regular slices. +\versionadded{2.3} + \end{description} % Internal types \end{description} % Types diff --git a/Lib/test/test_slice.py b/Lib/test/test_slice.py new file mode 100644 index 0000000..895238f --- /dev/null +++ b/Lib/test/test_slice.py @@ -0,0 +1,14 @@ +# tests for slice objects; in particular the indices method. + +from test_support import vereq + +vereq(slice(None ).indices(10), (0, 10, 1)) +vereq(slice(None, None, 2).indices(10), (0, 10, 2)) +vereq(slice(1, None, 2).indices(10), (1, 10, 2)) +vereq(slice(None, None, -1).indices(10), (9, -1, -1)) +vereq(slice(None, None, -2).indices(10), (9, -1, -2)) +vereq(slice(3, None, -2).indices(10), (3, -1, -2)) +vereq(slice(-100, 100 ).indices(10), slice(None).indices(10)) +vereq(slice(100, -100, -1).indices(10), slice(None, None, -1).indices(10)) +vereq(slice(-100L, 100L, 2L).indices(10), (0, 10, 2)) + diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c index a43644d..f2d84da 100644 --- a/Objects/sliceobject.c +++ b/Objects/sliceobject.c @@ -221,6 +221,39 @@ static PyMemberDef slice_members[] = { {0} }; +static PyObject* +slice_indices(PySliceObject* self, PyObject* len) +{ + int ilen, start, stop, step, slicelength; + + ilen = PyInt_AsLong(len); + + if (ilen == -1 && PyErr_Occurred()) { + return NULL; + } + + if (PySlice_GetIndicesEx(self, ilen, &start, &stop, + &step, &slicelength) < 0) { + return NULL; + } + + return Py_BuildValue("(lll)", start, stop, step); +} + +PyDoc_STRVAR(slice_indices_doc, +"S.indices(len) -> (start, stop, stride)\n\ +\n\ +Assuming a sequence of length len, calculate the start and stop\n\ +indices, and the stride length of the extended slice described by\n\ +S. Out of bounds indices are clipped in a manner consistent with the\n\ +handling of normal slices."); + +static PyMethodDef slice_methods[] = { + {"indices", (PyCFuntion)slice_indices, + METH_O, slice_indices_doc}, + {NULL, NULL} +}; + static int slice_compare(PySliceObject *v, PySliceObject *w) { @@ -271,7 +304,7 @@ PyTypeObject PySlice_Type = { 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + slice_methods, /* tp_methods */ slice_members, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ |