Foundations showed list[0] for one item. Today: list[a:b] for a range of items.
numbers = [10, 20, 30, 40, 50]
numbers[1:4] # [20, 30, 40]1:4 — starts at index 1, stops before index 4. Three items.
Right. The shape is [start:stop] — start is inclusive, stop is exclusive. The number of items is stop - start.
What if I omit one or both?
Defaults are sensible:
numbers[:3] # [10, 20, 30] — from start to index 3
numbers[2:] # [30, 40, 50] — from index 2 to end
numbers[:] # [10, 20, 30, 40, 50] — copy of the whole listNegative indices work too — counting from the end:
numbers[-2:] # [40, 50] — last two
numbers[:-2] # [10, 20, 30] — everything except last twoAnd there's a third number I've seen — the step?
[start:stop:step]. Default step is 1. Step 2 takes every other item:
numbers[::2] # [10, 30, 50] — every other, from start
numbers[1::2] # [20, 40] — every other, starting at index 1Negative step reverses:
numbers[::-1] # [50, 40, 30, 20, 10] — reversed copy[::-1] is the canonical Python idiom for "reverse a list or string."
Same syntax for strings?
Same syntax — strings are sliceable too:
"hello"[1:4] # 'ell'
"hello"[::-1] # 'olleh'[start:stop:step]sequence[start:stop] # default step = 1
sequence[start:stop:step]start — first index included (default 0)stop — first index excluded (default len(sequence))step — gap between indices (default 1)numbers = [10, 20, 30, 40, 50]
text = "hello"
numbers[1:4] # [20, 30, 40]
text[1:4] # 'ell'xs[:n] # first n items
xs[-n:] # last n items
xs[n:] # everything from index n onward
xs[:-n] # everything except last n
xs[::2] # every other item
xs[::-1] # reversed copy
xs[:] # full copy (useful when you need a mutable copy)"abcde"[::-1] # 'edcba'
[1, 2, 3][::-1] # [3, 2, 1]More generally, step = -1 walks backwards:
numbers[4:1:-1] # [50, 40, 30] — from index 4 down to (but not including) 1Readable? Marginally. Most code sticks to [::-1] for full reverse and uses regular slices for everything else.
A single-index lookup past the end raises:
[1, 2, 3][10] # IndexErrorA slice past the end is silently truncated:
[1, 2, 3][10:20] # [] — no error
[1, 2, 3][:100] # [1, 2, 3]Useful — and a small footgun (you might miss bugs that produce empty slices).
original = [1, 2, 3, 4]
part = original[1:3]
part.append(99)
original # [1, 2, 3, 4] — unchangedThe slice is a fresh copy. Modifying it doesn't touch the original. (Strings are immutable, so this only matters for lists.)
xs = [1, 2, 3, 4, 5]
xs[1:4] = [99] # replace indices 1-3 with a single item
xs # [1, 99, 5]Length can change. The right-hand side can be any iterable.
xs[1:4] is items at indices 1, 2, 3 — not 4.xs[-1] is the last item; xs[::-1] is the whole thing reversed. Different operators, different effects.Foundations showed list[0] for one item. Today: list[a:b] for a range of items.
numbers = [10, 20, 30, 40, 50]
numbers[1:4] # [20, 30, 40]1:4 — starts at index 1, stops before index 4. Three items.
Right. The shape is [start:stop] — start is inclusive, stop is exclusive. The number of items is stop - start.
What if I omit one or both?
Defaults are sensible:
numbers[:3] # [10, 20, 30] — from start to index 3
numbers[2:] # [30, 40, 50] — from index 2 to end
numbers[:] # [10, 20, 30, 40, 50] — copy of the whole listNegative indices work too — counting from the end:
numbers[-2:] # [40, 50] — last two
numbers[:-2] # [10, 20, 30] — everything except last twoAnd there's a third number I've seen — the step?
[start:stop:step]. Default step is 1. Step 2 takes every other item:
numbers[::2] # [10, 30, 50] — every other, from start
numbers[1::2] # [20, 40] — every other, starting at index 1Negative step reverses:
numbers[::-1] # [50, 40, 30, 20, 10] — reversed copy[::-1] is the canonical Python idiom for "reverse a list or string."
Same syntax for strings?
Same syntax — strings are sliceable too:
"hello"[1:4] # 'ell'
"hello"[::-1] # 'olleh'[start:stop:step]sequence[start:stop] # default step = 1
sequence[start:stop:step]start — first index included (default 0)stop — first index excluded (default len(sequence))step — gap between indices (default 1)numbers = [10, 20, 30, 40, 50]
text = "hello"
numbers[1:4] # [20, 30, 40]
text[1:4] # 'ell'xs[:n] # first n items
xs[-n:] # last n items
xs[n:] # everything from index n onward
xs[:-n] # everything except last n
xs[::2] # every other item
xs[::-1] # reversed copy
xs[:] # full copy (useful when you need a mutable copy)"abcde"[::-1] # 'edcba'
[1, 2, 3][::-1] # [3, 2, 1]More generally, step = -1 walks backwards:
numbers[4:1:-1] # [50, 40, 30] — from index 4 down to (but not including) 1Readable? Marginally. Most code sticks to [::-1] for full reverse and uses regular slices for everything else.
A single-index lookup past the end raises:
[1, 2, 3][10] # IndexErrorA slice past the end is silently truncated:
[1, 2, 3][10:20] # [] — no error
[1, 2, 3][:100] # [1, 2, 3]Useful — and a small footgun (you might miss bugs that produce empty slices).
original = [1, 2, 3, 4]
part = original[1:3]
part.append(99)
original # [1, 2, 3, 4] — unchangedThe slice is a fresh copy. Modifying it doesn't touch the original. (Strings are immutable, so this only matters for lists.)
xs = [1, 2, 3, 4, 5]
xs[1:4] = [99] # replace indices 1-3 with a single item
xs # [1, 99, 5]Length can change. The right-hand side can be any iterable.
xs[1:4] is items at indices 1, 2, 3 — not 4.xs[-1] is the last item; xs[::-1] is the whole thing reversed. Different operators, different effects.Create a free account to get started. Paid plans unlock all tracks.