mirror of
https://github.com/python/cpython.git
synced 2025-08-01 15:43:13 +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
|
@ -2473,6 +2473,9 @@ list_subscript(PyListObject* self, PyObject* item)
|
|||
if (slicelength <= 0) {
|
||||
return PyList_New(0);
|
||||
}
|
||||
else if (step == 1) {
|
||||
return list_slice(self, start, stop);
|
||||
}
|
||||
else {
|
||||
result = PyList_New(slicelength);
|
||||
if (!result) return NULL;
|
||||
|
@ -2516,10 +2519,15 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* treat L[slice(a,b)] = v _exactly_ like L[a:b] = v */
|
||||
if (step == 1 && ((PySliceObject*)item)->step == Py_None)
|
||||
if (step == 1)
|
||||
return list_ass_slice(self, start, stop, value);
|
||||
|
||||
/* Make sure s[5:2] = [..] inserts at the right place:
|
||||
before 5, not before 2. */
|
||||
if ((step < 0 && start < stop) ||
|
||||
(step > 0 && start > stop))
|
||||
stop = start;
|
||||
|
||||
if (value == NULL) {
|
||||
/* delete slice */
|
||||
PyObject **garbage;
|
||||
|
@ -2541,12 +2549,16 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* drawing pictures might help
|
||||
understand these for loops */
|
||||
/* drawing pictures might help understand these for
|
||||
loops. Basically, we memmove the parts of the
|
||||
list that are *not* part of the slice: step-1
|
||||
items for each item that is part of the slice,
|
||||
and then tail end of the list that was not
|
||||
covered by the slice */
|
||||
for (cur = start, i = 0;
|
||||
cur < stop;
|
||||
cur += step, i++) {
|
||||
Py_ssize_t lim = step;
|
||||
Py_ssize_t lim = step - 1;
|
||||
|
||||
garbage[i] = PyList_GET_ITEM(self, cur);
|
||||
|
||||
|
@ -2558,11 +2570,12 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
|||
self->ob_item + cur + 1,
|
||||
lim * sizeof(PyObject *));
|
||||
}
|
||||
|
||||
for (cur = start + slicelength*step + 1;
|
||||
cur < Py_Size(self); cur++) {
|
||||
PyList_SET_ITEM(self, cur - slicelength,
|
||||
PyList_GET_ITEM(self, cur));
|
||||
cur = start + slicelength*step;
|
||||
if (cur < Py_Size(self)) {
|
||||
memmove(self->ob_item + cur - slicelength,
|
||||
self->ob_item + cur,
|
||||
(Py_Size(self) - cur) *
|
||||
sizeof(PyObject *));
|
||||
}
|
||||
|
||||
Py_Size(self) -= slicelength;
|
||||
|
@ -2577,7 +2590,8 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
|||
}
|
||||
else {
|
||||
/* assign slice */
|
||||
PyObject **garbage, *ins, *seq, **seqitems, **selfitems;
|
||||
PyObject *ins, *seq;
|
||||
PyObject **garbage, **seqitems, **selfitems;
|
||||
Py_ssize_t cur, i;
|
||||
|
||||
/* protect against a[::-1] = a */
|
||||
|
@ -2587,14 +2601,17 @@ list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
|
|||
}
|
||||
else {
|
||||
seq = PySequence_Fast(value,
|
||||
"must assign iterable to extended slice");
|
||||
"must assign iterable "
|
||||
"to extended slice");
|
||||
}
|
||||
if (!seq)
|
||||
return -1;
|
||||
|
||||
if (PySequence_Fast_GET_SIZE(seq) != slicelength) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"attempt to assign sequence of size %zd to extended slice of size %zd",
|
||||
"attempt to assign sequence of "
|
||||
"size %zd to extended slice of "
|
||||
"size %zd",
|
||||
PySequence_Fast_GET_SIZE(seq),
|
||||
slicelength);
|
||||
Py_DECREF(seq);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue