The syntax is:
a[start:stop] # items start through stop-1
a[start:] # items start through the rest of the array
a[:stop] # items from the beginning through stop-1
a[:] # a copy of the whole array
There is also the step value, which can be used with any of the above:
a[start:stop:step] # start through not past stop, by step
The key point to remember is that the :stop value represents the first value that is not in the selected slice. So, the difference between stop and start is the number of elements selected (if step is 1, the default).
The other feature is that start or stop may be a negative number, which means it counts from the end of the array instead of the beginning. So:
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
Similarly, step may be a negative number:
a[::-1] # all items in the array, reversed
a[1::-1] # the first two items, reversed
a[:-3:-1] # the last two items, reversed
a[-3::-1] # everything except the last two items, reversed
Python is kind to the programmer if there are fewer items than you ask for. For example, if you ask for a[:-2] and a only contains one element, you get an empty list instead of an error. Sometimes you would prefer the error, so you have to be aware that this may happen.
Relationship with the slice object
A slice object can represent a slicing operation, i.e.:
a[start:stop:step]
is equivalent to:
a[slice(start, stop, step)]
Slice objects also behave slightly differently depending on the number of arguments, similar to range(), i.e. both slice(stop) and slice(start, stop[, step]) are supported.
To skip specifying a given argument, one might use None, so that e.g. a[start:] is equivalent to a[slice(start, None)] or a[::-1] is equivalent to a[slice(None, None, -1)].
While the :-based notation is very helpful for simple slicing, the explicit use of slice() objects simplifies the programmatic generation of slicing.
The syntax is:
a[start:stop] # items start through stop-1
a[start:] # items start through the rest of the array
a[:stop] # items from the beginning through stop-1
a[:] # a copy of the whole array
There is also the step value, which can be used with any of the above:
a[start:stop:step] # start through not past stop, by step
The key point to remember is that the :stop value represents the first value that is not in the selected slice. So, the difference between stop and start is the number of elements selected (if step is 1, the default).
The other feature is that start or stop may be a negative number, which means it counts from the end of the array instead of the beginning. So:
a[-1] # last item in the array
a[-2:] # last two items in the array
a[:-2] # everything except the last two items
Similarly, step may be a negative number:
a[::-1] # all items in the array, reversed
a[1::-1] # the first two items, reversed
a[:-3:-1] # the last two items, reversed
a[-3::-1] # everything except the last two items, reversed
Python is kind to the programmer if there are fewer items than you ask for. For example, if you ask for a[:-2] and a only contains one element, you get an empty list instead of an error. Sometimes you would prefer the error, so you have to be aware that this may happen.
Relationship with the slice object
A slice object can represent a slicing operation, i.e.:
a[start:stop:step]
is equivalent to:
a[slice(start, stop, step)]
Slice objects also behave slightly differently depending on the number of arguments, similar to range(), i.e. both slice(stop) and slice(start, stop[, step]) are supported.
To skip specifying a given argument, one might use None, so that e.g. a[start:] is equivalent to a[slice(start, None)] or a[::-1] is equivalent to a[slice(None, None, -1)].
While the :-based notation is very helpful for simple slicing, the explicit use of slice() objects simplifies the programmatic generation of slicing.
The Python tutorial talks about it (scroll down a bit until you get to the part about slicing).
The ASCII art diagram is helpful too for remembering how slices work:
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5
-6 -5 -4 -3 -2 -1
One way to remember how slices work is to think of the indices as pointing between characters, with the left edge of the first character numbered 0. Then the right edge of the last character of a string of n characters has index n.
This is a question that keeps coming back over and over. Somehow, this question got relevance in the search engines, but is lacking a comprehensive answer.
The square brackets syntax being discussed here is called "slicing", sometimes also referred as "extended indexing syntax". The formal definition of slicing can be found here, but as any formal definition, it can be very hard to understand for someone just wanting to use it.
In summary what it means, for the most common use-case, is the following:
primary[start:stop:step]
In the notation above:
primary: is any variable or literal expression that supports index access, such as a string, a list or a tuple. Other objects may support this syntax too, if implementing the necessary dunder methods (let's keep it simple for now, more about this later).start: the index of the first element that should be included in the slice. Python indices start from 0 (zero)!stop: the index of the element where the slicing should stop. IMPORTANT: the element at thestopposition will NOT be included! See examples below.step: (also calledstride) represents the size of the "jump" of each iteration fromstarttostop
Some additional notes:
- A negative integer for
startorstopmeans counting from the end of the list backwards, but the direction of the slice is still the same (which is controlled by the sign ofstep). That is to say, negative numbers are just an alternative way to place the starting and ending point of a slice - A negative integer for the
stepinverts the direction and the sorting of the resulting slice, effectively starting from thestop(this time inclusive) position and going backwards to thestart(exclusive) position.
Just to be clear:
- If
stepis not set or positive, the slice will include the element atstartindex, but not the one atstopindex; - If
stepis negative, the slice will include the element atstopindex, but not the one atstartindex. Also, the resulting list will have the elements in reverse order.
I know all this sounds confusing and the examples below should help to clarify:
>>> numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> numbers[2:9] # slice from 3rd to 9th items (9th not included)
[2, 3, 4, 5, 6, 7, 8]
>>> numbers[-8:-1] # Index -8 == index 2 and index -1 == index 9
[2, 3, 4, 5, 6, 7, 8]
>>> numbers[2:9:2] # Take every second element in the slice
[2, 4, 6, 8]
>>> numbers[-8:-1:2] # Same effect as above
[2, 4, 6, 8]
>>> numbers[2:9:-1] # Trying to go from 3rd to 9th element in reverse
[] # results in an empty list
>>> numbers[9:2:-1] # Step is now negative. Slice is in reverse order,
[9, 8, 7, 6, 5, 4, 3] # from `stop` to `start` position (not included)
>>> numbers[-1:-8:-1] # Same effect as above
[9, 8, 7, 6, 5, 4, 3]
>>> numbers[-1:-8:-2] # Take every second element in reverse
[9, 7, 5, 3]
Some useful shorthand forms:
>>> numbers[:] # shallow copy
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> numbers[::-1] # reversed shallow copy
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
As mentioned above, third party objects can support this syntax if implementing the __getitem__ dunder method for integer keys. Remarkable examples are NumPy, Pandas, and many others.
Notes about the original question:
The OP reports dealing with a list x of 32 elements and wants to do some math with it. More specifically they say:
x[:-N+1]I want to access all elements except the last twox[N:-N]I want to access all elements except the first one and the last onex[N+1:]I want to access all elements except the first
I'm not entirely sure what they meant by N in the formulas, but the way to achieve the desired result is rather simple:
- To access all elements except the last two:
x[:-2] - To access all elements except the first and last one:
x[1:-1] - To access all elements except the first:
x[1:]
Notice, however, that the first two slices will have 30 elements and the third slice will have 31. Doing algebraic operations with matrices/vectors of different shape won't work. That's probably something you'll want to fix.
Slice except the last two: x[:N-2]
Except first and last: x[1:N-1]
Except first two: x[2:]
Python slice can be obtained by:
x[starting_index:end_index] {including starting_index element and excluding end_index}
If you don't specify the starting_index, it becomes 0 by default.
If you don't specify the end_index, it becomes N by default.