datarekha
Python Easy Asked at AmazonAsked at Google

How does Python list slicing work, including step and negative indices?

The short answer

Slicing uses the syntax `seq[start:stop:step]` and returns a new list containing elements from index `start` up to but not including `stop`, stepping by `step`. Negative indices count from the end; a negative step reverses direction. Omitted parts default to the beginning, end, or step of 1.

How to think about it

How to approach this in an interview

Slicing looks simple but the edge cases — negative indices, negative steps, out-of-range bounds — trip up a lot of candidates. The cleanest way to explain it is to start with the three parameters and build up: start, then stop, then step. The mental model that helps most: think of indices as sitting between elements, not on them.

Basic syntax

The full form is seq[start:stop:step]. Stop is exclusive — the element at the stop index is not included. That matches Python’s range(start, stop) convention.

data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

data[2:5]      # [2, 3, 4]       — indices 2, 3, 4 (stop=5 excluded)
data[:4]       # [0, 1, 2, 3]    — from start
data[6:]       # [6, 7, 8, 9]    — to end
data[:]        # full shallow copy
data[::2]      # [0, 2, 4, 6, 8] — every other element
data[::-1]     # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] — reversed

Negative indices and steps

Negative index -k is equivalent to len(data) - k. So -1 is the last element, -2 the second-to-last, and so on.

data[-3:]      # [7, 8, 9]  — last three elements
data[-3:-1]    # [7, 8]     — stop is still exclusive
data[8:2:-1]   # [8, 7, 6, 5, 4, 3] — step backwards from index 8 down to 3

Interactive playground — experiment with slicing

Out-of-range slices do not raise

data[100:]     # []   — no IndexError; slices clamp silently
data[:100]     # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Contrast this with single-index access: data[100] raises IndexError. Slices are more forgiving because they describe a range rather than a specific position.

Slice assignment modifies in place

nums = [1, 2, 3, 4, 5]
nums[1:3] = [20, 30, 40]   # replace two elements with three
print(nums)   # [1, 20, 30, 40, 4, 5]

nums[::2] = [0, 0, 0]      # when step != 1, replacement must match length

Strings and tuples follow the same rules

Both return a new object of the same type. String slicing is a clean way to parse fixed-width fields without regex: row[10:20] for a fixed-width log format.

Learn it properly Lists

Keep practising

All Python questions

Explore further

Skip to content