List Slicing

Snip snip

List Slicing Basics

What if, given a list, we only want a subsection of this list? That is, what if we want to slice this list? We can do so in Python! In Python syntax, we can slice a list like list[start:stop], with the start being inclusive and stop being exclusive.
>>> lst = [1, 2, 3, 4]
>>> lst[1:3]
[2, 3]
>>> lst[1:4]
[2, 3, 4]
Notice how the stop index can be beyond the indices of the list — lst[4] does not exist. Similarly, lst[1:5] or lst[1:6] works the exact same way.
Can we also do this to the starting index? Say, lst[-2:5]? No, actually! This is because negative indices in a list are counting from the end. lst[-1] is 4, lst[-2] is 3, and so on. Thus, the starting index specified as lst[-2:5] is equivalent to lst[2:5] instead.
Note that list slicing creates a copy of the list — it does not edit the original list.

Specifying Step Size

We can also specify a step size in our list slicing.
>>> lst = [1, 2, 3, 4]
>>> lst[1:3:2]
>>> lst[0:4:2]
[1, 3]
>>> lst[4:0:-1]
[4, 3, 2, 1]
Note how in the last one we specified 4 as the starting index. This is because, on step size -1, to get the entire list, we wish to start at the end and move one step backwards through the list until we reach 1. If we were to instead write lst[0:4:-1], then the list would start at the first element and try to go backwards — never being able to reach 4. This would return an empty list. Thus, we have to be careful about the start and stop values when step size is negative.
This also leaves us with another insight: If it is not possible to reach the specified stop index from the start index, given the step size, an empty list is returned. Try some impossible slices yourself to test this out!

Empty Index Slicing

There is one more interesting format to list slicing — specifying nothing for start or stop.
>>> lst[:3]
When we specify nothing as the start or stop index, we consider it a stand-in for specifying the end or beginning of the list. Keep this in mind as we mess around with a few examples.
>>> lst = [1, 2, 3, 4]
>>> lst[:3]
[1, 2, 3]
>>> lst[1:]
[2, 3, 4]
>>> lst[::-1]
[4, 3, 2, 1]
Empty indexing also gives us a unique power that's more than just syntactical comfort. Consider the two following statements: lst[0:4:-1] and lst[::-1]. These two should technically be equivalent — for the given list, both say to start from the start and end at the end, going -1 steps at a time. But they yield different results, as seen in the examples above.
>>> lst = [1, 2, 3, 4]
>>> lst[0:4:-1]
>>> lst[::-1]
[4, 3, 2, 1]
What is going on here?
Unlike specifying a number, the empty index matches the start or the end of a list. That is, in lst[::-1], it starts at the end, and takes -1 steps all the way to the beginning of the list.
List slicing is deceptively complex! Try out some examples with list slicing to develop intuition.