What a slice is
Sometimes you need only part of a list, such as the first few items. Slicing copies that part into a new list. Write the start index and the end index in brackets with a colon between them. The item at the end index is not included, so letters[1:4] holds the items at indexes 1, 2 and 3. The length is easy to see: 4 - 1 = 3 items.
letters = ["a", "b", "c", "d", "e"]
print(letters[1:4])
print(letters[:2])
print(letters[3:])
print(letters[-2:])
print(letters[3:100])
print(letters[4:2])
['b', 'c', 'd']
['a', 'b']
['d', 'e']
['d', 'e']
['d', 'e']
[]
- Leave out the start to begin at index 0, and leave out the end to run to the very end of the list.
- Negative indexes count from the end, so
letters[-2:]is the last two items. - A slice never fails on an index that is too big:
letters[3:100]is simply the items from index 3 on. - If the start is not before the end, the slice is an empty list.
The original stays as it was
A slice is a new list. Changing the slice does not change the original, and slicing does not change it either. A slice with no bounds, letters[:], is a copy of the whole list:
copy = letters[:]
copy.append("f")
print(letters)
print(copy)
['a', 'b', 'c', 'd', 'e']
['a', 'b', 'c', 'd', 'e', 'f']
The lesson's task
runners holds five runners in the order they finished. The first three go on the podium: runners[:3] starts at index 0 and stops before index 3, so it holds the items at 0, 1 and 2. Everyone else is runners[3:], from index 3 to the end. The code then prints both lists and the length of runners, which is still 5 because slicing left it alone.
runners = ["Ana", "Ben", "Cleo", "Dan", "Eve"]
podium = runners[:3]
rest = runners[3:]
print(podium[0], podium[1], podium[2])
print(rest[0], rest[1])
print(len(runners))
Ana Ben Cleo
Dan Eve
5
Common mistakes
- Expecting the end index to be included.
runners[:3]has three items, not four. - Using
runners[3](one item) whererunners[3:](a list) is needed.
Steps and the whole list
A slice can take a third number, the step: my_list[i:j:k] takes every k-th item. A step of -1 walks backward, which reverses the list. Negative bounds count from the end, so w[:-1] is everything but the last item.
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(nums[::2])
print(nums[::-1])
print(nums[2:8:3])
w = ["a", "b", "c", "d", "e"]
print(w[:-1])
print(w[-3:-1])
[0, 2, 4, 6, 8]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
[2, 5]
['a', 'b', 'c', 'd']
['c', 'd']
Slicing works on strings and tuples too, and gives a string or a tuple: "hello"[1:3] is "el".
Slicing against indexing
One index, like runners[3], gives a single item: "Dan". A slice, like runners[3:4], gives a list with that one item: ['Dan']. Indexing past the end raises an IndexError, while slicing past the end quietly gives what exists. That is why runners[3:] is safe even when a race has only three runners: it is simply an empty list.
A slice is a good way to replace a loop that picks "the first n" or "all but the last". It also pairs with assignment: w[1:3] = ["X"] replaces the items at indexes 1 and 2 with one item, so the list changes length. The lesson only needs to read slices, but it helps to know the same brackets can write.
Key takeaways
my_list[i:j]is a new list of the items fromiup to, not including,j.- Either bound can be left out, and a big end index is safe.
- The original list doesn't change.
