diff options
author | Thomas Wouters <thomas@python.org> | 2007-08-28 15:28:19 +0000 |
---|---|---|
committer | Thomas Wouters <thomas@python.org> | 2007-08-28 15:28:19 +0000 |
commit | 3ccec68a05abae43cf74dc7821c61ba88ab6cb46 (patch) | |
tree | 07e97200d168eec13110e16a11b974310b8b550a /Objects/listobject.c | |
parent | 0f4a14b56fcbd939e60f424517db61ca6f2f3885 (diff) | |
download | cpython-git-3ccec68a05abae43cf74dc7821c61ba88ab6cb46.tar.gz |
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.
Diffstat (limited to 'Objects/listobject.c')
-rw-r--r-- | Objects/listobject.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/Objects/listobject.c b/Objects/listobject.c index ac0d0183a0..c0621dce91 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -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); |