Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5efaf7e

Browse files
author
Michael W. Hudson
committed
This is my nearly two year old patch
[ 400998 ] experimental support for extended slicing on lists somewhat spruced up and better tested than it was when I wrote it. Includes docs & tests. The whatsnew section needs expanding, and arrays should support extended slices -- later.
1 parent f90ae20 commit 5efaf7e

13 files changed

Lines changed: 570 additions & 22 deletions

File tree

Doc/api/concrete.tex

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,6 +2288,32 @@ \subsection{Slice Objects \label{slice-objects}}
22882288

22892289
\begin{cfuncdesc}{int}{PySlice_GetIndices}{PySliceObject *slice, int length,
22902290
int *start, int *stop, int *step}
2291+
Retrieve the start, stop and step indices from the slice object
2292+
\var{slice}, assuming a sequence of length \var{length}. Treats
2293+
indices greater than \var{length} as errors.
2294+
2295+
Returns 0 on success and -1 on error with no exception set (unless one
2296+
of the indices was not \constant{None} and failed to be converted to
2297+
an integer, in which case -1 is returned with an exception set).
2298+
2299+
You probably do not want to use this function. If you want to use
2300+
slice objects in versions of Python prior to 2.3, you would probably
2301+
do well to incorporate the source of \cfunction{PySlice_GetIndicesEx},
2302+
suitably renamed, in the source of your extension.
2303+
\end{cfuncdesc}
2304+
2305+
\begin{cfuncdesc}{int}{PySlice_GetIndicesEx}{PySliceObject *slice, int length,
2306+
int *start, int *stop, int *step,
2307+
int *slicelength}
2308+
Usable replacement for \cfunction{PySlice_GetIndices}. Retrieve the
2309+
start, stop, and step indices from the slice object \var{slice}
2310+
assuming a sequence of length \var{length}, and store the length of
2311+
the slice in \var{slicelength}. Out of bounds indices are clipped in
2312+
a manner consistent with the handling of normal slices.
2313+
2314+
Returns 0 on success and -1 on error with exception set.
2315+
2316+
\versionadded{2.3}
22912317
\end{cfuncdesc}
22922318

22932319

Doc/lib/libstdtypes.tex

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ \subsection{Sequence Types \label{typesseq}}
433433
\hline
434434
\lineiii{\var{s}[\var{i}]}{\var{i}'th item of \var{s}, origin 0}{(2)}
435435
\lineiii{\var{s}[\var{i}:\var{j}]}{slice of \var{s} from \var{i} to \var{j}}{(2), (3)}
436+
\lineiii{\var{s}[\var{i}:\var{j}:\var{k}]}{slice of \var{s} from \var{i} to \var{j} with step \var{k}}{(2), (4)}
436437
\hline
437438
\lineiii{len(\var{s})}{length of \var{s}}{}
438439
\lineiii{min(\var{s})}{smallest item of \var{s}}{}
@@ -446,6 +447,7 @@ \subsection{Sequence Types \label{typesseq}}
446447
\indexii{repetition}{operation}
447448
\indexii{subscript}{operation}
448449
\indexii{slice}{operation}
450+
\indexii{extended slice}{operation}
449451
\opindex{in}
450452
\opindex{not in}
451453

@@ -492,6 +494,15 @@ \subsection{Sequence Types \label{typesseq}}
492494
\code{len(\var{s})}, use \code{len(\var{s})}. If \var{i} is omitted,
493495
use \code{0}. If \var{j} is omitted, use \code{len(\var{s})}. If
494496
\var{i} is greater than or equal to \var{j}, the slice is empty.
497+
498+
\item[(4)] The slice of \var{s} from \var{i} to \var{j} with step \var{k}
499+
is defined as the sequence of items with index \code{\var{x} =
500+
\var{i} + \var{n}*\var{k}} such that \var{n} \code{>=} \code{0} and
501+
\code{\var{i} <= \var{x} < \var{j}}. If \var{i} or \var{j} is
502+
greater than \code{len(\var{s})}, use \code{len(\var{s})}. If
503+
\var{i} or \var{j} are ommitted then they become ``end'' values
504+
(which end depends on the sign of \var{k}).
505+
495506
\end{description}
496507

497508

@@ -875,31 +886,36 @@ \subsubsection{Mutable Sequence Types \label{typesseq-mutable}}
875886
{slice of \var{s} from \var{i} to \var{j} is replaced by \var{t}}{}
876887
\lineiii{del \var{s}[\var{i}:\var{j}]}
877888
{same as \code{\var{s}[\var{i}:\var{j}] = []}}{}
889+
\lineiii{\var{s}[\var{i}:\var{j}:\var{k}] = \var{t}}
890+
{the elements of \code{\var{s}[\var{i}:\var{j}:\var{k}]} are replaced by those of \var{t}}{(1)}
891+
\lineiii{del \var{s}[\var{i}:\var{j}:\var{k}]}
892+
{removes the elements of \code{\var{s}[\var{i}:\var{j}:\var{k}]} from the list}{}
878893
\lineiii{\var{s}.append(\var{x})}
879-
{same as \code{\var{s}[len(\var{s}):len(\var{s})] = [\var{x}]}}{(1)}
894+
{same as \code{\var{s}[len(\var{s}):len(\var{s})] = [\var{x}]}}{(2)}
880895
\lineiii{\var{s}.extend(\var{x})}
881-
{same as \code{\var{s}[len(\var{s}):len(\var{s})] = \var{x}}}{(2)}
896+
{same as \code{\var{s}[len(\var{s}):len(\var{s})] = \var{x}}}{(3)}
882897
\lineiii{\var{s}.count(\var{x})}
883898
{return number of \var{i}'s for which \code{\var{s}[\var{i}] == \var{x}}}{}
884899
\lineiii{\var{s}.index(\var{x})}
885-
{return smallest \var{i} such that \code{\var{s}[\var{i}] == \var{x}}}{(3)}
900+
{return smallest \var{i} such that \code{\var{s}[\var{i}] == \var{x}}}{(4)}
886901
\lineiii{\var{s}.insert(\var{i}, \var{x})}
887902
{same as \code{\var{s}[\var{i}:\var{i}] = [\var{x}]}
888-
if \code{\var{i} >= 0}}{(4)}
903+
if \code{\var{i} >= 0}}{(5)}
889904
\lineiii{\var{s}.pop(\optional{\var{i}})}
890-
{same as \code{\var{x} = \var{s}[\var{i}]; del \var{s}[\var{i}]; return \var{x}}}{(5)}
905+
{same as \code{\var{x} = \var{s}[\var{i}]; del \var{s}[\var{i}]; return \var{x}}}{(6)}
891906
\lineiii{\var{s}.remove(\var{x})}
892-
{same as \code{del \var{s}[\var{s}.index(\var{x})]}}{(3)}
907+
{same as \code{del \var{s}[\var{s}.index(\var{x})]}}{(4)}
893908
\lineiii{\var{s}.reverse()}
894-
{reverses the items of \var{s} in place}{(6)}
909+
{reverses the items of \var{s} in place}{(7)}
895910
\lineiii{\var{s}.sort(\optional{\var{cmpfunc}})}
896-
{sort the items of \var{s} in place}{(6), (7)}
911+
{sort the items of \var{s} in place}{(7), (8)}
897912
\end{tableiii}
898913
\indexiv{operations on}{mutable}{sequence}{types}
899914
\indexiii{operations on}{sequence}{types}
900915
\indexiii{operations on}{list}{type}
901916
\indexii{subscript}{assignment}
902917
\indexii{slice}{assignment}
918+
\indexii{extended slice}{assignment}
903919
\stindex{del}
904920
\withsubitem{(list method)}{
905921
\ttindex{append()}\ttindex{extend()}\ttindex{count()}\ttindex{index()}
@@ -908,32 +924,35 @@ \subsubsection{Mutable Sequence Types \label{typesseq-mutable}}
908924
\noindent
909925
Notes:
910926
\begin{description}
911-
\item[(1)] The C implementation of Python has historically accepted
927+
\item[(1)] \var{t} must have the same length as the slice it is
928+
replacing.
929+
930+
\item[(2)] The C implementation of Python has historically accepted
912931
multiple parameters and implicitly joined them into a tuple; this
913932
no longer works in Python 2.0. Use of this misfeature has been
914933
deprecated since Python 1.4.
915934

916-
\item[(2)] Raises an exception when \var{x} is not a list object. The
935+
\item[(3)] Raises an exception when \var{x} is not a list object. The
917936
\method{extend()} method is experimental and not supported by
918937
mutable sequence types other than lists.
919938

920-
\item[(3)] Raises \exception{ValueError} when \var{x} is not found in
939+
\item[(4)] Raises \exception{ValueError} when \var{x} is not found in
921940
\var{s}.
922941

923-
\item[(4)] When a negative index is passed as the first parameter to
942+
\item[(5)] When a negative index is passed as the first parameter to
924943
the \method{insert()} method, the new element is prepended to the
925944
sequence.
926945

927-
\item[(5)] The \method{pop()} method is only supported by the list and
946+
\item[(6)] The \method{pop()} method is only supported by the list and
928947
array types. The optional argument \var{i} defaults to \code{-1},
929948
so that by default the last item is removed and returned.
930949

931-
\item[(6)] The \method{sort()} and \method{reverse()} methods modify the
950+
\item[(7)] The \method{sort()} and \method{reverse()} methods modify the
932951
list in place for economy of space when sorting or reversing a large
933952
list. To remind you that they operate by side effect, they don't return
934953
the sorted or reversed list.
935954

936-
\item[(7)] The \method{sort()} method takes an optional argument
955+
\item[(8)] The \method{sort()} method takes an optional argument
937956
specifying a comparison function of two arguments (list items) which
938957
should return a negative, zero or positive number depending on whether
939958
the first argument is considered smaller than, equal to, or larger

Doc/ref/ref3.tex

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,13 @@ \section{The standard type hierarchy\label{types}}
252252
renumbered so that it starts at 0.
253253
\index{slicing}
254254

255+
Some sequences also support ``extended slicing'' with a third ``step''
256+
parameter: \code{\var{a}[\var{i}:\var{j}:\var{k}]} selects all items
257+
of \var{a} with index \var{x} where \code{\var{x} = \var{i} +
258+
\var{n}*\var{k}}, \var{n} \code{>=} \code{0} and \var{i} \code{<=}
259+
\var{x} \code{<} \var{j}.
260+
\index{extended slicing}
261+
255262
Sequences are distinguished according to their mutability:
256263

257264
\begin{description}

Doc/whatsnew/whatsnew23.tex

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,15 @@ \section{PEP 285: The \class{bool} Type\label{section-bool}}
336336

337337
\end{seealso}
338338

339+
\section{Extended Slices\label{extended-slices}}
340+
341+
Ever since Python 1.4 the slice syntax has supported a third
342+
``stride'' argument, but the builtin sequence types have not supported
343+
this feature (it was initially included at the behest of the
344+
developers of the Numerical Python package). This changes with Python
345+
2.3.
346+
347+
% XXX examples, etc.
339348

340349
%======================================================================
341350
%\section{Other Language Changes}

Include/sliceobject.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ DL_IMPORT(PyObject *) PySlice_New(PyObject* start, PyObject* stop,
3232
PyObject* step);
3333
DL_IMPORT(int) PySlice_GetIndices(PySliceObject *r, int length,
3434
int *start, int *stop, int *step);
35+
DL_IMPORT(int) PySlice_GetIndicesEx(PySliceObject *r, int length,
36+
int *start, int *stop,
37+
int *step, int *slicelength);
3538

3639
#ifdef __cplusplus
3740
}

Lib/test/test_bool.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ class C(bool):
219219
veris(operator.isSequenceType([]), True)
220220
veris(operator.contains([], 1), False)
221221
veris(operator.contains([1], 1), True)
222-
veris(operator.isMappingType([]), False)
222+
veris(operator.isMappingType(1), False)
223223
veris(operator.isMappingType({}), True)
224224
veris(operator.lt(0, 0), False)
225225
veris(operator.lt(0, 1), True)

Lib/test/test_types.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,31 @@ class C: pass
188188
x = 'x'*103
189189
if '%s!'%x != x+'!': raise TestFailed, 'nasty string formatting bug'
190190

191+
#extended slices for strings
192+
a = '0123456789'
193+
vereq(a[::], a)
194+
vereq(a[::2], '02468')
195+
vereq(a[1::2], '13579')
196+
vereq(a[::-1],'9876543210')
197+
vereq(a[::-2], '97531')
198+
vereq(a[3::-2], '31')
199+
vereq(a[-100:100:], a)
200+
vereq(a[100:-100:-1], a[::-1])
201+
vereq(a[-100L:100L:2L], '02468')
202+
203+
if have_unicode:
204+
a = unicode('0123456789', 'ascii')
205+
vereq(a[::], a)
206+
vereq(a[::2], unicode('02468', 'ascii'))
207+
vereq(a[1::2], unicode('13579', 'ascii'))
208+
vereq(a[::-1], unicode('9876543210', 'ascii'))
209+
vereq(a[::-2], unicode('97531', 'ascii'))
210+
vereq(a[3::-2], unicode('31', 'ascii'))
211+
vereq(a[-100:100:], a)
212+
vereq(a[100:-100:-1], a[::-1])
213+
vereq(a[-100L:100L:2L], unicode('02468', 'ascii'))
214+
215+
191216
print '6.5.2 Tuples'
192217
if len(()) != 0: raise TestFailed, 'len(())'
193218
if len((1,)) != 1: raise TestFailed, 'len((1,))'
@@ -207,6 +232,19 @@ class C: pass
207232
x += (1,)
208233
if x != (1,): raise TestFailed, 'tuple resize from () failed'
209234

235+
# extended slicing - subscript only for tuples
236+
a = (0,1,2,3,4)
237+
vereq(a[::], a)
238+
vereq(a[::2], (0,2,4))
239+
vereq(a[1::2], (1,3))
240+
vereq(a[::-1], (4,3,2,1,0))
241+
vereq(a[::-2], (4,2,0))
242+
vereq(a[3::-2], (3,1))
243+
vereq(a[-100:100:], a)
244+
vereq(a[100:-100:-1], a[::-1])
245+
vereq(a[-100L:100L:2L], (0,2,4))
246+
247+
210248
print '6.5.3 Lists'
211249
if len([]) != 0: raise TestFailed, 'len([])'
212250
if len([1,]) != 1: raise TestFailed, 'len([1,])'
@@ -322,6 +360,40 @@ def myComparison(x,y):
322360
if a[ 3: pow(2,145L) ] != [3,4]:
323361
raise TestFailed, "list slicing with too-large long integer"
324362

363+
364+
# extended slicing
365+
366+
# subscript
367+
a = [0,1,2,3,4]
368+
vereq(a[::], a)
369+
vereq(a[::2], [0,2,4])
370+
vereq(a[1::2], [1,3])
371+
vereq(a[::-1], [4,3,2,1,0])
372+
vereq(a[::-2], [4,2,0])
373+
vereq(a[3::-2], [3,1])
374+
vereq(a[-100:100:], a)
375+
vereq(a[100:-100:-1], a[::-1])
376+
vereq(a[-100L:100L:2L], [0,2,4])
377+
# deletion
378+
del a[::2]
379+
vereq(a, [1,3])
380+
a = range(5)
381+
del a[1::2]
382+
vereq(a, [0,2,4])
383+
a = range(5)
384+
del a[1::-2]
385+
vereq(a, [0,2,3,4])
386+
# assignment
387+
a = range(10)
388+
a[::2] = [-1]*5
389+
vereq(a, [-1, 1, -1, 3, -1, 5, -1, 7, -1, 9])
390+
a = range(10)
391+
a[::-4] = [10]*3
392+
vereq(a, [0, 10, 2, 3, 4, 10, 6, 7, 8 ,10])
393+
a = range(4)
394+
a[::-1] = a
395+
vereq(a, [3, 2, 1, 0])
396+
325397
print '6.6 Mappings == Dictionaries'
326398
d = {}
327399
if d.keys() != []: raise TestFailed, '{}.keys()'

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ Type/class unification and new-style classes
66

77
Core and builtins
88

9+
- Most builtin sequences now support "extended slices", i.e. slices
10+
with a third "stride" parameter. For example, "range(10)[1:6:2]"
11+
evaluates to [1, 3, 5].
12+
913
- Cycles going through the __class__ link of a new-style instance are
1014
now detected by the garbage collector.
1115

0 commit comments

Comments
 (0)