Python Slice Notation Guide

Python Slice Notation Guide

Explain Python’s slice notation


Python slicing is a computationally fast way to methodically access parts of your data. In my opinion, to be even an intermediate Python programmer, it’s one aspect of the language that it is necessary to be familiar with.

In short, the colons (:) in subscript notation make slice notation - which has the optional arguments, start, stop, step:

sequence[start:stop:step]

Important Definitions

To begin with, let’s define a few terms:

start: the beginning index of the slice, it will include the element at this index unless it is the same as stop, defaults to 0, i.e. the first index. If it’s negative, it means to start n items from the end.

stop : the ending index of the slice, it does not include the element at this index, defaults to length of the sequence being sliced, that is, up to and including the end.

step : the amount by which the index increases, defaults to 1. If it’s negative, you’re slicing over the iterable in reverse.

And recall, there are defaults for start, stop, and step, so to access the defaults, simply leave out the argument.

Mostly used variations
s[start:end]
s[start:]
s[:end]

Step-related variations
s[:end:step]
s[start::step]
s[::step]

Make a copy
s[:]

example:

mylist[X:Y]

  • X is the index of the first element you want.
  • Y is the index of the first element you don’t want.

Another Definition

We work with sequence indexes. But there exist another way how to look on python slicing with positive step.
One way to remember how slices work is to think of the indices as pointing between characters, with the left or right edge of the first/last character marked as :. Table below show this situation.

Examples


We use this table for slice explanation. You can see list and slices indexes for list a=[1,2,3,4,5,6]

Python indexes and slices for a six-element list.
Indexes enumerate the elements, slices enumerate the spaces between the elements.

Index from rear:    -6  -5  -4  -3  -2  -1      a=[1,2,3,4,5,6]    a[1:]==[2,3,4,5,6]
Index from front:    0   1   2   3   4   5      len(a)==6          a[:5]==[1,2,3,4,5]
                   +---+---+---+---+---+---+    a[0]==1            a[:-2]==[1,2,3,4]
                   | 1 | 2 | 3 | 4 | 5 | 6 |    a[5]==6            a[1:2]==[2]
                   +---+---+---+---+---+---+    a[-1]==6           a[1:-1]==[2,3,4,5]
Slice from front:  :   1   2   3   4   5   :    a[-2]==5           a[1:-2]==[2,3,4]
Slice from rear:   :  -5  -4  -3  -2  -1   :
                                                b=a[:]
                                                b==[1,2,3,4,5,6] (shallow copy of a)
>>> a=[1,2,3,4,5,6]

>>> a[0:4]    # first 4 items
[1, 2, 3, 4]

>>> a[:4]     # first 4 items
[1, 2, 3, 4]

>>> a[1:4]
[2, 3, 4]

>>> a[1:2]
[2]

>>> a[1:]     # all items without first
[2, 3, 4, 5, 6]

>>> a[0:-1]   # all items withou last
[1, 2, 3, 4, 5]

>>> a[:5]
[1, 2, 3, 4, 5]

>>> a[-3:]    # last 3 items
[4, 5, 6]

>>> a[:-2]    # all items without last two
[1, 2, 3, 4]

>>> a[1:-1]
[2, 3, 4, 5]

>>> a[1:-2]
[2, 3, 4]

examples with positive steps:

>>> b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

>>> b[0::2]
[1, 3, 5, 7, 9]

>>> b[0::3]
[1, 4, 7, 10]

>>> b[0::4]
[1, 5, 9]

>>> b[0:-2:2]
[1, 3, 5, 7]

When step is negative, the defaults for start and stop change

By default, when the step argument is empty (or None), it is assigned to +1.

But you can pass in a negative integer, and the list (or most other standard slicables) will be sliced from the end to the beginning.

Thus a negative slice will change the defaults for start and stop! The default then for start is -1 and stop is calculated as -(len(sequence) + 1).

Python indexes and slices for a six-element list.
Indexes enumerate the elements, slices enumerate the spaces between the elements.

Index from rear:    -6  -5  -4  -3  -2  -1      a=[1,2,3,4,5,6]    a[1:]==[2,3,4,5,6]
Index from front:    0   1   2   3   4   5      len(a)==6          a[:5]==[1,2,3,4,5]
                   +---+---+---+---+---+---+    a[0]==1            a[:-2]==[1,2,3,4]
                   | 1 | 2 | 3 | 4 | 5 | 6 |    a[5]==6            a[1:2]==[2]
                   +---+---+---+---+---+---+    a[-1]==6           a[1:-1]==[2,3,4,5]
Slice from front:  :   1   2   3   4   5   :    a[-2]==5           a[1:-2]==[2,3,4]
Slice from rear:   :  -5  -4  -3  -2  -1   :
                                                b=a[:]
                                                b==[1,2,3,4,5,6] (shallow copy of a)

Understanding index assignment is very important:

In forward direction, starts at 0 and ends at len(sequence) - 1

In backward direction, starts at -1 and ends at -(len(sequence) + 1)

NOTE that end index will not be included in the resulted slice

examples:

a = [1, 2, 3, 4, 5, 6]

a[::-1]        # reverse list    
[6, 5, 4, 3, 2, 1]

a[-1::-1]      # reverse list
[6, 5, 4, 3, 2, 1]

a[:-7:-1]     # reverse list  
[6, 5, 4, 3, 2, 1]

a[-1:-7:-1]   # reverse list
[6, 5, 4, 3, 2, 1]

a[::-2]
[6, 4, 2]

a[-2::-2]
[5, 3, 1]

a[-1:-5:-2] 
[6, 4]

Interesting Slices


a[-1]      # last item in the array
a[-2:]     # last two items in the array
a[:-1]     # everything except last item
a[:-2]     # everything except the last two items
a[2:-1]    # everything except first two and last one item

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

Slice first n and last m items

You can specify both positive and negative indices at the same time.

L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
print(L[2:-5])
# Prints ['c', 'd']

Modify Multiple List Values

You can modify multiple list items at once with slice assignment. This assignment replaces the specified slice of a list with the items of assigned iterable.

# Modify multiple list items
L = ['a', 'b', 'c', 'd', 'e']
L[1:4] = [1, 2, 3]
print(L)
# Prints ['a', 1, 2, 3, 'e']
# Replace multiple elements in place of a single element
L = ['a', 'b', 'c', 'd', 'e']
L[1:2] = [1, 2, 3]
print(L)
# Prints ['a', 1, 2, 3, 'c', 'd', 'e']

Insert Multiple List Items

You can insert items into a list without replacing anything. Simply specify a zero-length slice.

# Insert at the start
L = ['a', 'b', 'c']
L[:0] = [1, 2, 3]
print(L)
# Prints [1, 2, 3, 'a', 'b', 'c']

# Insert at the end
L = ['a', 'b', 'c']
L[len(L):] = [1, 2, 3]
print(L)
# Prints ['a', 'b', 'c', 1, 2, 3]

You can insert items into the middle of list by keeping both the start and stop indices of the slice same.

# Insert in the middle
L = ['a', 'b', 'c']
L[1:1] = [1, 2, 3]
print(L)
# Prints ['a', 1, 2, 3, 'b', 'c']

Delete Multiple List Items

You can delete multiple items out of the middle of a list by assigning the appropriate slice to an empty list.

L = ['a', 'b', 'c', 'd', 'e']
L[1:5] = []
print(L)
# Prints ['a']

You can also use the del statement with the same slice.

L = ['a', 'b', 'c', 'd', 'e']
del L[1:5]
print(L)
# Prints ['a']