mirror of
https://github.com/python/cpython.git
synced 2025-07-30 06:34:15 +00:00
Improve extended slicing support in builtin types and classes. Specifically:
- Specialcase extended slices that amount to a shallow copy the same way as is done for simple slices, in the tuple, string and unicode case. - Specialcase step-1 extended slices to optimize the common case for all involved types. - For lists, allow extended slice assignment of differing lengths as long as the step is 1. (Previously, 'l[:2:1] = []' failed even though 'l[:2] = []' and 'l[:2:None] = []' do not.) - Implement extended slicing for buffer, array, structseq, mmap and UserString.UserString. - Implement slice-object support (but not non-step-1 slice assignment) for UserString.MutableString. - Add tests for all new functionality.
This commit is contained in:
parent
0f4a14b56f
commit
3ccec68a05
16 changed files with 730 additions and 120 deletions
|
@ -89,6 +89,54 @@ structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high)
|
|||
return (PyObject *) np;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
structseq_subscript(PyStructSequence *self, PyObject *item)
|
||||
{
|
||||
if (PyIndex_Check(item)) {
|
||||
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||
if (i == -1 && PyErr_Occurred())
|
||||
return NULL;
|
||||
|
||||
if (i < 0)
|
||||
i += VISIBLE_SIZE(self);
|
||||
|
||||
if (i < 0 || i >= VISIBLE_SIZE(self)) {
|
||||
PyErr_SetString(PyExc_IndexError,
|
||||
"tuple index out of range");
|
||||
return NULL;
|
||||
}
|
||||
Py_INCREF(self->ob_item[i]);
|
||||
return self->ob_item[i];
|
||||
}
|
||||
else if (PySlice_Check(item)) {
|
||||
Py_ssize_t start, stop, step, slicelen, cur, i;
|
||||
PyObject *result;
|
||||
|
||||
if (PySlice_GetIndicesEx((PySliceObject *)item,
|
||||
VISIBLE_SIZE(self), &start, &stop,
|
||||
&step, &slicelen) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (slicelen <= 0)
|
||||
return PyTuple_New(0);
|
||||
result = PyTuple_New(slicelen);
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
for (cur = start, i = 0; i < slicelen;
|
||||
cur += step, i++) {
|
||||
PyObject *v = self->ob_item[cur];
|
||||
Py_INCREF(v);
|
||||
PyTuple_SET_ITEM(result, i, v);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"structseq index must be integer");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
|
@ -298,6 +346,11 @@ static PySequenceMethods structseq_as_sequence = {
|
|||
(objobjproc)structseq_contains, /* sq_contains */
|
||||
};
|
||||
|
||||
static PyMappingMethods structseq_as_mapping = {
|
||||
(lenfunc)structseq_length,
|
||||
(binaryfunc)structseq_subscript,
|
||||
};
|
||||
|
||||
static PyMethodDef structseq_methods[] = {
|
||||
{"__reduce__", (PyCFunction)structseq_reduce,
|
||||
METH_NOARGS, NULL},
|
||||
|
@ -317,7 +370,7 @@ static PyTypeObject _struct_sequence_template = {
|
|||
(reprfunc)structseq_repr, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
&structseq_as_sequence, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
&structseq_as_mapping, /* tp_as_mapping */
|
||||
structseq_hash, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue