[Tutor] What exactly is [::-1]?

Chris Calloway cbc at unc.edu
Thu Jul 26 21:37:54 CEST 2007

Kent Johnson wrote:
> AFAIK extended slicing is not supported by any standard Python data 
> types, it was added specifically for Numeric.

Numeric *is* responsible for getting *one* of the two forms of extended 
slicing added (the one with multiple slices or ellipses separated by 
commas) and yes, that *one form* isn't supported by any builtin or 
"standard" global module Python data types.

The *other* form of extended slicing, the one with two colons (and no 
commas) is supported by typeseq objects, though.

The phrase "extended slicing" probably ought to be clarified in the 
documentation as having two distinct forms (stepped and multiple). This 
is a root of considerable confusion for people reading about extended 
slicing in the standard documentation.

Extended slicing is really talking about two ways of creating a *slice 
object* (and there are other ways of creating slice objects). And not 
all slice objects are created equally as far as typeseq and array module 
objects are concerned.

A sensible solution would be to refer to the stepped form as a simple 
slice and realize that both "stepped simple" slices and comma-extended 
slices create slice objects in Python 2.3 and later. I don't know how 
wise it would be to further confuse the issue by changing the 
documentation at this point. It's a judgment call.

Using stepped slicing with numpy/Numeric/numarray style arrays is also 
very different from using it with the standard array module and typeseq 

With typeseq objects, the two colon extended slicing provides a reversed 
*copy* of the typeseq object as opposed to the .reverse method which 
reverses a typeseq object *in place* (and has no return value):

 >>> a = [0,1,2,3,4]
 >>> b = a[::-1]
 >>> a[2] = 6
 >>> a.reverse()
 >>> a
[4, 3, 6, 1, 0]
 >>> b
[4, 3, 2, 1, 0]

Same with the array module (a copy is made):

 >>> import array
 >>> e = array.array('i',[0,1,2,3,4])
 >>> f = e[::-1]
 >>> e[2] = 23
 >>> e.reverse()
 >>> e
array('i', [4, 3, 23, 1, 0])
 >>> f
array('i', [4, 3, 2, 1, 0])

However, with numpy/Numeric/numarray style arrays, extended slicing 
gives you a "view" of the original array, somewhat similar to using 
.reverse() on typeseq objects (but still different because the original 
array is unchanged). Changes to the original array will be *reflected* 
in the view objects of that original array (unlike in the example copied 
objects above):

 >>> import numpy
 >>> c = numpy.array([0, 1, 2, 3, 4])
 >>> d = c[::-1]
 >>> c[2] = 9
 >>> c
array([0, 1, 9, 3, 4])
 >>> d
array([4, 3, 9, 1, 0])

To get a reversed *copy* of numpy/Numeric/numarray style arrays, you'll 
need to use their .copy() method on the extended slice. 
numpy/Numeric/numarray style arrays have no .reverse() method as typeseq 
and array module objects do:

 >>> g = c[::-1].copy()
 >>> c[2] = 42
 >>> c
array([ 0,  1, 42,  3,  4])
 >>> g
array([4, 3, 9, 1, 0])
 >>> c.reverse()
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
AttributeError: 'numpy.ndarray' object has no attribute 'reverse'

So that extended slicing of the form [::-1] is kind of necessary with 
numpy/Numeric/numarray style arrays in order to "reverse" the object. 
Just remember, double colon extended slicing has a different effect on 
typeseq and array module objects (by making a copy).


Chris Calloway
office: 332 Chapman Hall   phone: (919) 962-4323
mail: Campus Box #3300, UNC-CH, Chapel Hill, NC 27599

More information about the Tutor mailing list