Learning Goals
3 minBy the end of this lesson you can:
- Read any item out of a list using its index.
- Use a negative index to reach the end without knowing the length.
- Take a run of items with a slice, and say why the end is excluded.
Warm-Up · Six Names in a Row
5 minYou have made lists before. Predict both lines.
club = ["Mia", "Leo", "Ana", "Hugo", "Ella", "Theo"] print(len(club)) print(club)
Answer
Output
6 ['Mia', 'Leo', 'Ana', 'Hugo', 'Ella', 'Theo']
Printing the whole list shows the brackets and quotes. Useful for checking, useless for showing anyone. To print names nicely you need them one at a time — which is today.
New Concept · Every Item Has a Number
12 minThink of a row of seats in the school hall. Each seat holds one person and has a number on the back. Give Python the number, it tells you who is sitting there.
The seats
Mia Leo Ana Hugo Ella Theo 0 1 2 3 4 5 -6 -5 -4 -3 -2 -1
Counting starts at 0. Six items, so the last is at index 5 — always len(club) - 1.
club = ["Mia", "Leo", "Ana", "Hugo", "Ella", "Theo"] print(club[0]) print(club[3]) print(club[-1]) print(club[-2])
Output
Mia Hugo Theo Ella
club[6] raises IndexError: list index out of range — there is no seat 6. And club[1.5] raises TypeError, because an index must be a whole number. Both are loud and immediate, which is the good kind of error.
Slicing — a run of items
Written list[start:stop], and it hands back a new list, not a single item.
club = ["Mia", "Leo", "Ana", "Hugo", "Ella", "Theo"] print(club[0:3]) print(club[3:6]) print(club[:2]) print(club[4:]) print(club[-2:])
Output
['Mia', 'Leo', 'Ana'] ['Hugo', 'Ella', 'Theo'] ['Mia', 'Leo'] ['Ella', 'Theo'] ['Ella', 'Theo']
The stop is excluded, so club[0:3] and club[3:6] fit together perfectly — no gap, no overlap. That is what makes splitting a list into two halves easy.
club[0] is the string "Mia". club[0:1] is the list ["Mia"]. They print differently and behave differently — you can add a list to a list, but not a string to a list. Reaching for the wrong one is a common early bug.
Why it matters. Top three scores, everyone except the first, the last five entries, the second half of a class — all of them are one slice. If you have written a loop with a counter to do that, this replaces it.
Worked Example · A Leaderboard
12 minOne list of scores, several views of it — and not a single counter variable.
# leaderboard.py - reading one list in several ways names = ["Leo", "Mia", "Ella", "Theo", "Ana", "Hugo"] scores = [95, 91, 88, 84, 79, 72] print("Players:", len(names)) print() print("Champion: ", names[0], "with", scores[0]) print("Runner-up: ", names[1], "with", scores[1]) print("Last place:", names[-1], "with", scores[-1]) print() # The two lists line up, so one index reads both podium = names[0:3] podium_scores = scores[0:3] print("Podium") for i in range(len(podium)): print(" ", i + 1, "-", podium[i], podium_scores[i]) print() print("Everyone else:", names[3:]) print("Bottom two: ", names[-2:]) gap = scores[0] - scores[-1] print() print("Gap between first and last:", gap)
Output
Players: 6 Champion: Leo with 95 Runner-up: Mia with 91 Last place: Hugo with 72 Podium 1 - Leo 95 2 - Mia 91 3 - Ella 88 Everyone else: ['Theo', 'Ana', 'Hugo'] Bottom two: ['Ana', 'Hugo'] Gap between first and last: 72
Two habits worth taking:
- Parallel lists share an index.
names[2]andscores[2]are the same player. It works, and it is fragile — sort one without the other and they no longer match. Section 3 · Dictionaries fixes that properly. [-1]beats[len(x) - 1]. Same answer, less to get wrong.
names[3:99] quietly returns whatever exists. That is forgiving, and it hides mistakes: if you expect five items and get two, nothing complains. Check with len() when the count matters.
Try It Yourself
13 minMake a list of seven days as strings. Print the first day, the last day, and how many days there are. Then print the middle day using an index you work out from len().
Hint
days = ["Isnin", "Selasa", "Rabu", "Khamis", "Jumaat", "Sabtu", "Ahad"] print("First:", days[0]) print("Last:", days[-1]) middle = len(days) // 2
Using the same list of seven days:
- Print the five weekdays as one list, and the two weekend days as another — slices only, no loops.
- Print the middle three days.
- Print the days in the order they appear, but starting from Wednesday and wrapping round to Tuesday. Two slices joined with
+will do it.
Mini-Challenge 🔥 · Debug: The Last Item That Was Not There
8 minHugo prints a class register. It crashes on the very last line, and one earlier line is quietly wrong. Find two mistakes.
# register.py - buggy
pupils = ["Mia", "Leo", "Ana", "Hugo"]
print("Class of", len(pupils))
for i in range(len(pupils)):
print(i, "-", pupils[i])
print("First:", pupils[1])
print("Last:", pupils[len(pupils)])Answer
pupils[len(pupils)]is one too far. The list has 4 items at indexes 0 to 3, so index 4 raisesIndexError: list index out of range. It should bepupils[len(pupils) - 1], or better,pupils[-1].pupils[1]is the second pupil, not the first. Counting starts at 0, so the first ispupils[0]. No error, just the wrong name — the sort of bug that survives to the printed register.
The working version:
# register.py - fixed pupils = ["Mia", "Leo", "Ana", "Hugo"] print("Class of", len(pupils)) for i in range(len(pupils)): print(i, "-", pupils[i]) print("First:", pupils[0]) print("Last:", pupils[-1])
Output
Class of 4 0 - Mia 1 - Leo 2 - Ana 3 - Hugo First: Mia Last: Hugo
Notice the loop was right all along: range(len(pupils)) gives 0, 1, 2, 3 — it stops before 4 for the same reason a slice does.
Recap
3 minA list is a numbered row of items, counted from 0 forwards and -1 backwards. items[i] gives one item; items[start:stop] gives a new list, stopping before stop. An index past the end raises IndexError, while a slice past the end quietly gives what exists.
Vocabulary Card
- index
- The position of one item, counting from 0.
- negative index
- A position from the end, where
-1is the last item. - slice
- A new list taken with
[start:stop], excludingstop. - IndexError
- Raised when you ask for a position the list does not have.
Homework
4 minWrite top_songs.py. Make a list of your ten favourite songs, best first.
- Print the number one, the number ten, and the total.
- Print the top three as a list, using one slice.
- Print songs four to seven inclusive — check your numbers carefully.
- Print the bottom three using negative indexes only.
- Finish by printing the middle song, worked out from
len()rather than typed in.
Bring the file next class.
Sample · top_songs.py
# top_songs.py - one list, read six different ways songs = [ "Sesuci Lebaran", "Flower Terakhir", "Kau Ilhamku", "Isabella", "Standing In The Eyes Of The World", "Gemuruh", "Terukir Di Star", "Hujan", "Ala Canggung", "Rasa Dear", ] print("Total songs:", len(songs)) print("Number one: ", songs[0]) print("Number ten: ", songs[-1]) print() print("Top three:", songs[0:3]) print("Four to seven:", songs[3:7]) print("Bottom three:", songs[-3:]) print() middle = len(songs) // 2 print("Middle song:", songs[middle], "at index", middle)
Output
Total songs: 10 Number one: Sesuci Lebaran Number ten: Rasa Dear Top three: ['Sesuci Lebaran', 'Flower Terakhir', 'Kau Ilhamku'] Four to seven: ['Isabella', 'Standing In The Eyes Of The World', 'Gemuruh', 'Terukir Di Star'] Bottom three: ['Hujan', 'Ala Canggung', 'Rasa Dear'] Middle song: Gemuruh at index 5
"Songs four to seven" is [3:7] — start one lower because counting begins at 0, stop one higher because the end is excluded. That double adjustment is the bit worth practising.