Slicing with Step

The third slice argument, counting from the end, and why the stop index is never included.

Overview

The stop is excluded

s[2:5]

gives the items at 2, 3 and 4. This is the same rule as range, and it has the same payoff: s[:3] and s[3:] split the sequence with no overlap and no gap, and the length of s[a:b] is b - a.

Leave either end off and it means "from the beginning" or "to the end". Leave both off and s[:] is the whole thing — which is the idiomatic shallow copy of a list.

slicing.py

slicing.py Python 3
Output

                    

slicing_lists.py

slicing_lists.py Python 3
Output

                    

Worth knowing

[start:stop:step], and the stop is never included.
Negative indices count from the end: -1 is the last item.
[::-1] reverses. [:] copies.
Slicing out of range is silent; indexing out of range raises IndexError.

Slicing with Step: A Practical Guide

A slice takes a piece of a sequence using up to three numbers: where to start, where to stop, and how big a step to take. Two rules explain nearly all of its behaviour.

Negative indices count from the right

s[-1]    # last item
s[-3:]   # last three
s[:-2]   # everything except the last two

-1 is the last element, not "one before the start". Mixing the two conventions is fine: s[2:-1] is "from index 2 to the second-to-last".

The third value is the step

s[::2]    # every second item
s[1::2]   # every second, starting at 1
s[::-1]   # reversed

[::-1] is the standard reverse idiom and worth memorising as one symbol rather than parsing each time. A negative step walks backwards, so start and stop swap roles — which is why s[5:2:-1] gives you something and s[2:5:-1] gives you nothing.

Slicing forgives, indexing does not

s[2:99]   # fine, gives what exists
s[99]     # IndexError

A slice clamps to the available range and returns what it can, including an empty result. That is convenient and occasionally hides a bug, because an empty slice looks like valid data rather than a mistake.

Slices copy, and assignment mutates

A slice of a list is a new list, so changing it leaves the original alone. But assigning into a slice changes the original in place, and can change its length:

nums[1:3] = ["a", "b", "c"]

replaces two items with three. That is a genuine feature and a genuine surprise.

Reversing three ways

data[::-1] builds a new reversed list. reversed(data) returns a lazy iterator and copies nothing. data.reverse() reorders in place and returns None — the same trap as .sort().

Check yourself

0 of 3

Answer without scrolling back up.

  1. What is `'abcdef'[1:4]`?

  2. What does `s[::-1]` do?

  3. `s[99]` raises IndexError but `s[2:99]` does not. Why?

Cheat sheet

Slicing with Step

A slice takes a piece of a sequence using up to three numbers: where to start, where to stop, and how big a step to take. Two rules explain nearly all of its behaviour.

PYTHON · vizlearn.in/python/slicing_step_negatives.html

About the author

Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.