Learning Goals
3 minBy the end of this lesson you can:
- Read and write slice expressions like
names[1:4],names[:3], andnames[-2:]with confidence. - Explain why
names[0:3]gives three items, not four — the "stop is exclusive" rule. - Use a slice to copy a list, grab a tail, or step through every other item.
Warm-Up
5 minLast lesson we changed lists with append, pop, remove, and sort. Today we're back to reading lists — but reading many items at once.
Predict the output. What does Python print?
drinks = ["teh tarik", "kopi-O", "milo ais", "sirap bandung", "limau ais"] print(drinks[1:4]) print(drinks[-1])
Show the answer
['kopi-O', 'milo ais', 'sirap bandung'] limau ais
drinks[1:4] gives positions 1, 2, and 3 — not position 4. The stop number is where to stop before. And drinks[-1] is a peek backwards: the very last drink, "limau ais".
New Concept · The Slice Shape
14 minFrom one item to many
You already know the single-item shape: my_list[i]. A slice uses a colon between two numbers:
my_list[start:stop]
It hands back a new list containing the items from index start up to but not including index stop.
The exclusive-stop rule (the big one)
This is the single rule that bites every beginner.
names = ["Hafiz", "Aisyah", "Daniel", "Mei", "Priya"] # 0 1 2 3 4 print(names[1:4]) # → ['Aisyah', 'Daniel', 'Mei'] # indices 1, 2, 3 — index 4 is NOT included
Why? Because stop - start equals the number of items you get back. names[1:4] gives 4 - 1 = 3 items. names[0:3] gives 3 items. Useful for double-checking your work.
Negative indices · reaching from the back
Python lets you index from the end with negative numbers:
names = ["Hafiz", "Aisyah", "Daniel", "Mei", "Priya"] # -5 -4 -3 -2 -1 print(names[-1]) print(names[-2]) # → Priya # → Mei
-1 is the last item, -2 the second-last, and so on. No more typing names[len(names) - 1] like a robot.
Open-ended slices · leave a side blank
Leave the start out and Python assumes from the very beginning. Leave the stop out and Python assumes all the way to the end.
names = ["Hafiz", "Aisyah", "Daniel", "Mei", "Priya"] print(names[:3]) # first three print(names[2:]) # from index 2 onwards print(names[-2:]) # last two print(names[:-1]) # everything except the last # → ['Hafiz', 'Aisyah', 'Daniel'] # → ['Daniel', 'Mei', 'Priya'] # → ['Mei', 'Priya'] # → ['Hafiz', 'Aisyah', 'Daniel', 'Mei']
names[:] · the full copy
Leave both sides blank and you get a brand-new copy of the whole list. Useful when you want to sort or modify a list without trashing the original.
names = ["Mei", "Hafiz", "Aisyah"] sorted_copy = names[:] sorted_copy.sort() print("Original:", names) print("Sorted copy:", sorted_copy) # → Original: ['Mei', 'Hafiz', 'Aisyah'] # → Sorted copy: ['Aisyah', 'Hafiz', 'Mei']
The third slot · step
A slice has a hidden third part — the step.
numbers = [10, 20, 30, 40, 50, 60, 70, 80] print(numbers[::2]) # every other item, starting from index 0 print(numbers[1::2]) # every other item, starting from index 1 # → [10, 30, 50, 70] # → [20, 40, 60, 80]
And the most famous trick of all — step -1 reverses the list:
names = ["Hafiz", "Aisyah", "Daniel"] print(names[::-1]) # → ['Daniel', 'Aisyah', 'Hafiz']
Unlike sort or append, a slice never changes the original. It returns a brand-new list. So names[1:4] on its own does nothing useful — you need print(names[1:4]) or first_three = names[:3] to capture the result.
Worked Example · Daniel's Top-3 Score Board
12 minThe job
Daniel records the bowling scores of every kid at the school party. He wants three reports: the top 3 scores, the bottom 3 scores, and the "middle of the pack" (everyone except the top and bottom three).
Step 1 · The raw scores
scores = [62, 88, 41, 95, 73, 58, 90, 70, 49, 81]
Step 2 · Sort highest-first
To find the top 3 we need the list in descending order.
scores.sort(reverse=True) print(scores) # → [95, 90, 88, 81, 73, 70, 62, 58, 49, 41]
Step 3 · Slice the top 3
top_three = scores[:3] print("Top 3:", top_three) # → Top 3: [95, 90, 88]
[:3] reads as "from the start up to (but not including) index 3" — that's positions 0, 1, 2: exactly three items.
Step 4 · Slice the bottom 3
bottom_three = scores[-3:] print("Bottom 3:", bottom_three) # → Bottom 3: [58, 49, 41]
[-3:] reads as "from three-from-the-end all the way to the end." A super-readable way to grab a tail.
Step 5 · The middle of the pack
middle = scores[3:-3] print("Middle:", middle) # → Middle: [81, 73, 70, 62]
Start at index 3 (skip the top three), stop at index -3 (skip the bottom three). The two cutoffs meet in the middle.
The complete script
Save as score_board.py:
Code
# score_board.py — Daniel's top-3 / bottom-3 / middle report scores = [62, 88, 41, 95, 73, 58, 90, 70, 49, 81] scores.sort(reverse=True) top_three = scores[:3] bottom_three = scores[-3:] middle = scores[3:-3] print("All scores (high to low):", scores) print("Top 3:", top_three) print("Bottom 3:", bottom_three) print("Middle:", middle)
Output
All scores (high to low): [95, 90, 88, 81, 73, 70, 62, 58, 49, 41] Top 3: [95, 90, 88] Bottom 3: [58, 49, 41] Middle: [81, 73, 70, 62]
Leaderboards, "recent activity" feeds, image galleries showing the latest 5, hawker apps showing the top 3 stalls — every one of them is a sort followed by a slice. You now have the toolkit.
Try It Yourself
13 minThree tasks. Predict the output in your head first, then run the code and check.
Given fruits = ["mango", "rambutan", "mangosteen", "durian", "langsat", "pomelo"], print the first three fruits on one line and the last three on the next.
Hint
fruits = ["mango", "rambutan", "mangosteen", "durian", "langsat", "pomelo"] print("First three:", fruits[:3]) print("Last three:", fruits[-3:])
[:3] means "from the start, three items". [-3:] means "three items from the end onwards". Notice how clean both are without using len().
Given scores = [50, 60, 70, 80, 90, 100], print only the every-other score starting from index 0 — so [50, 70, 90].
Hint
scores = [50, 60, 70, 80, 90, 100] every_other = scores[::2] print(every_other)
The third slot is the step. scores[::2] reads as "from start to end, taking every 2nd item."
Given names = ["Hafiz", "Aisyah", "Daniel", "Mei"], print the names backwards but leave the original list unchanged. Prove it by printing names at the very end.
Hint
names = ["Hafiz", "Aisyah", "Daniel", "Mei"] backwards = names[::-1] print("Backwards:", backwards) print("Original:", names)
Step -1 walks the slice backwards. Because slicing always builds a new list, the original is untouched — perfect when you need both views.
Mini-Challenge · Priya's Surprise Output
8 minPriya wants the first four kuih on a tray of six. She writes:
kuih = ["kuih lapis", "ondeh-ondeh", "seri muka", "kuih bahulu", "kuih dadar", "kuih cara"] first_four = kuih[1:4] print(first_four)
She expected four kuih. She got three — and the wrong three! What did she mean to write, and why was she off?
Show the fix
kuih = ["kuih lapis", "ondeh-ondeh", "seri muka", "kuih bahulu", "kuih dadar", "kuih cara"] first_four = kuih[:4] print(first_four) # → ['kuih lapis', 'ondeh-ondeh', 'seri muka', 'kuih bahulu']
Two bugs in one. First, Priya started at index 1, not 0, so she skipped "kuih lapis". Second, kuih[1:4] gives 4 - 1 = 3 items, not 4 — because the stop is exclusive. The fix is kuih[:4]: start at the beginning, stop before index 4, which means items 0/1/2/3 — exactly four. Whenever a slice looks off, count stop - start first.
Recap
3 minA slice is "a window into a list." The shape is list[start:stop], the stop is always exclusive, and either side can be left blank. Negative indices count from the back, and the optional third slot — the step — lets you skip or reverse. Best of all, slicing never changes the original list, so you can experiment freely.
Vocabulary Card
- slice
- A range of items pulled from a list, written
list[start:stop]. Returns a new list. - exclusive stop
- The stop number is the index Python stops before.
list[0:3]returns 3 items, not 4. - negative index
- Counts from the end.
list[-1]is the last item,list[-2]the second-last. - open-ended slice
- A slice with a missing side, like
list[:3]orlist[2:]. The missing side defaults to the start or the end. - step
- The third slot in
list[start:stop:step].2takes every other item;-1reverses. - full copy
list[:]— a brand-new list with the same items. Perfect when you want to sort without trashing the original.
Homework
4 minCreate a new file leaderboard.py — a class-quiz leaderboard.
- Start with a list
scoresof at least 8 quiz marks (whole numbers from 0 to 100). - Sort the list highest-first using
scores.sort(reverse=True). - Use slicing to grab and print the top 3.
- Use slicing to grab and print the bottom 2.
- Use slicing to grab and print the middle band (everyone except the top 3 and bottom 2).
- At the end, print the original list in its sorted order plus its length.
Bring leaderboard.py next class — in PY-L1-19 we'll add randomness with random.choice and random.shuffle.
Sample · leaderboard.py
# leaderboard.py — class quiz leaderboard scores = [62, 88, 41, 95, 73, 58, 90, 70, 49, 81] scores.sort(reverse=True) top_three = scores[:3] bottom_two = scores[-2:] middle = scores[3:-2] print("All scores (high to low):", scores) print("Top 3:", top_three) print("Bottom 2:", bottom_two) print("Middle:", middle) print("How many students:", len(scores))
Your numbers can be different — eight or more, any whole-number marks. The non-negotiables are: sort(reverse=True) first, then [:3] for the top, [-2:] for the bottom, and [3:-2] for the middle. If your middle band came out wrong, check the cutoffs match (3 skipped on the left, 2 skipped on the right).