WasiLearn Code
Python · Data structures

Slicing: taking pieces of a list

A bus display in Karachi does not show all fourteen stops on the route. It shows the next three. The full route is still in your program — you just need a piece of it on screen.

Python has a piece-taking notation built into square brackets, and it works the same way on lists and on strings.

stops = ["Saddar", "Gulshan", "Nazimabad", "Korangi", "Clifton"]
print(stops[0:3])
output
['Saddar', 'Gulshan', 'Nazimabad']

That is a slice: [start:stop]. It starts at index 0 and stops before index 3, giving you the first three stops. The original list is untouched — a slice hands you a brand new list.

Leaving an end off

Writing 0 at the front is common enough that Python lets you drop it. Leave out the start and the slice begins at the beginning; leave out the stop and it runs to the end.

stops = ["Saddar", "Gulshan", "Nazimabad", "Korangi", "Clifton"]
print(stops[:3])
print(stops[3:])
print(stops[:])
output
['Saddar', 'Gulshan', 'Nazimabad']
['Korangi', 'Clifton']
['Saddar', 'Gulshan', 'Nazimabad', 'Korangi', 'Clifton']

Read stops[:3] as "up to 3" and stops[3:] as "from 3 onwards". The two of them together cover the whole list exactly once, with no item appearing twice. That is not luck — it falls out of how the stop works, which is the next section.

The stop is not included

Here is the mistake that costs people an afternoon. You want the second, third and fourth scores from a cricket innings, so you write [1:3] and expect three numbers back.

scores = [12, 45, 8, 67, 23]
print(scores[1:3])
print(len(scores[1:3]))
output
[45, 8]
2

Two, not three. The belief looks perfectly reasonable — you named index 1 and index 3, so surely you get 1, 2 and 3. But stop is not the last index you want. It is the first index you do not want. The slice walks forward and halts the moment it reaches that number.

You have already met this rule. range(1, 3) gives you 1 and 2, never 3. Python uses one convention everywhere it describes a span, and slices follow it.

Once you accept the rule, it pays you back. The length of [a:b] is simply b - a, so [1:3] is 2 items and [0:3] is 3 items — no counting on your fingers. And stops[:3] followed by stops[3:] splits a list cleanly at 3, because the item at index 3 belongs to exactly one of them.

So to get scores 1, 2 and 3, ask for one past the last one you want:

scores = [12, 45, 8, 67, 23]
print(scores[1:4])
output
[45, 8, 67]

There is a second, kinder surprise here. A single index that does not exist crashes:

scores = [12, 45, 8]
print(scores[7])

A slice that runs off the end does not. It quietly gives you whatever it can find:

scores = [12, 45, 8]
print(scores[1:99])
print(scores[7:9])
output
[45, 8]
[]

That is genuinely useful when you want "the next three, or fewer if the route is nearly over", but it is also a trap: a slice never tells you it came up short. If the count matters, check len() yourself.

Counting from the right

Negative numbers count backwards from the end, and they work in slices just as they do in a plain index.

stops = ["Saddar", "Gulshan", "Nazimabad", "Korangi", "Clifton"]
print(stops[-2:])
print(stops[:-1])
print(stops[-3:-1])
output
['Korangi', 'Clifton']
['Saddar', 'Gulshan', 'Nazimabad', 'Korangi']
['Nazimabad', 'Korangi']

stops[-2:] is the last two stops. stops[:-1] is everything except the last one — useful for "all the stops before the terminus". And the exclusive rule still holds in [-3:-1]: it stops before -1, so Clifton is left out.

Every second item: the step

A slice takes a third number, after a second colon: [start:stop:step]. The step is how far to jump each time, and it defaults to 1.

overs = [4, 12, 0, 8, 15, 3, 9, 21]
print(overs[::2])
print(overs[1::2])
print(overs[2:7:3])
output
[4, 0, 15, 9]
[12, 8, 3, 21]
[0, 3]

overs[::2] takes index 0, 2, 4, 6 — every other run total. Starting at 1 instead gives you the ones it skipped. Splitting a list into two alternating halves takes two slices and no loop at all.

Reversing with [::-1]

A negative step walks backwards, and it is the shortest way to reverse anything in Python.

overs = [4, 12, 0, 8, 15, 3, 9, 21]
print(overs[::-1])
output
[21, 9, 3, 15, 8, 0, 12, 4]

Read [::-1] as "the whole thing, one step at a time, backwards". Both ends are left blank on purpose, because with a negative step Python starts at the end and finishes at the beginning.

Mixing a negative step with a forward start and stop is where people come unstuck:

overs = [4, 12, 0, 8, 15, 3, 9, 21]
print(overs[0:3:-1])
output
[]

Nothing. You asked to start at 0 and walk backwards while staying above 3, which is impossible on the first step. When you use a negative step, your start must be to the right of your stop.

Slicing strings

A string is a sequence of characters, so every rule above applies to it unchanged. Slicing a string gives you a shorter string.

code = "PK-2026-KHI"
print(code[:2])
print(code[3:7])
print(code[-3:])
output
PK
2026
KHI

That is how you pull fields out of a fixed-width code without any cleverness. And [::-1] reverses a string exactly as it reverses a list, which gives you a palindrome check in one line:

word = "malayalam"
print(word == word[::-1])
output
True

A slice is always a new list

This is the part worth carrying forward. Slicing never edits the thing you slice — it builds a fresh one and hands it over. So a change to the slice cannot reach back and disturb the original.

prices = [120, 45, 80]
canteen = prices[:]
canteen[0] = 999
print(prices)
print(canteen)
output
[120, 45, 80]
[999, 45, 80]

prices[:] is a slice with both ends left off, so it copies everything. It is the oldest way in Python to make a separate list that starts out identical to another one, and it matters more than it looks — writing canteen = prices instead would give you two names for one list, and the print above would show 999 twice. The list methods lesson takes that apart properly.

Until then: if you want a piece, slice it. If you want a safe copy, slice all of it.

Related reading: the lists lesson for indexing and len(), the strings lesson for what else a string can do, and the loops lesson for the range() rule that slicing borrows.

Prefer learning with a teacher?

WasiLearn Academy runs small-group classes covering this material, online and in Karachi.

See the classes