List slicing is one of Python’s most elegant features — a concise syntax for extracting portions of a list without writing explicit loops. Once you internalize the [start:end:step] pattern, you’ll use it constantly.
Basic Syntax#
list[start:end:step]
start— index of the first element to include (default: beginning)end— index of the first element to exclude (default: end)step— interval between elements (default: 1)
The key insight: start is inclusive, end is exclusive.
Start and End Indices#
fruits = ['apple', 'banana', 'cherry', 'date', 'fig', 'grape']
sublist = fruits[1:4]
print(sublist)
# Output: ['banana', 'cherry', 'date']
Elements at indices 1, 2, and 3 are included — but not index 4.
Omitting Indices#
Leave out start to begin from the first element, or end to go through the last:
fruits = ['apple', 'banana', 'cherry', 'date', 'fig', 'grape']
first_three = fruits[:3]
print(first_three)
# Output: ['apple', 'banana', 'cherry']
last_three = fruits[-3:]
print(last_three)
# Output: ['date', 'fig', 'grape']
Omit both to get a shallow copy of the entire list:
copy = fruits[:]
Negative Indexing#
Python lists support negative indices, where -1 is the last element, -2 is second to last, and so on:
fruits = ['apple', 'banana', 'cherry', 'date', 'fig', 'grape']
print(fruits[-1])
# Output: 'grape'
print(fruits[-3:-1])
# Output: ['date', 'fig']
Negative indices are especially useful when you don’t know the list length.
Step Value#
The third parameter controls how many elements to skip:
fruits = ['apple', 'banana', 'cherry', 'date', 'fig', 'grape']
every_other = fruits[::2]
print(every_other)
# Output: ['apple', 'cherry', 'fig']
every_third = fruits[::3]
print(every_third)
# Output: ['apple', 'date']
Reversing a List#
A negative step traverses the list backwards. The most common pattern is [::-1]:
fruits = ['apple', 'banana', 'cherry', 'date', 'fig', 'grape']
reversed_list = fruits[::-1]
print(reversed_list)
# Output: ['grape', 'fig', 'date', 'cherry', 'banana', 'apple']
This creates a new reversed list without modifying the original. Compare with list.reverse(), which reverses in place.
Slice Assignment#
Slices aren’t just for reading — you can assign to them to replace, insert, or delete sections:
nums = [0, 1, 2, 3, 4, 5]
# Replace a section
nums[1:4] = [10, 20, 30]
print(nums)
# Output: [0, 10, 20, 30, 4, 5]
# Insert without removing (empty slice)
nums[2:2] = [99, 98]
print(nums)
# Output: [0, 10, 99, 98, 20, 30, 4, 5]
# Delete a section
nums[2:4] = []
print(nums)
# Output: [0, 10, 20, 30, 4, 5]
Slicing Strings and Tuples#
Slicing works identically on any sequence type:
text = "Hello, World!"
print(text[7:12])
# Output: 'World'
print(text[::-1])
# Output: '!dlroW ,olleH'
coords = (10, 20, 30, 40, 50)
print(coords[1:4])
# Output: (20, 30, 40)
The difference: strings and tuples are immutable, so you can’t do slice assignment on them.
The slice Object#
For reusable slices, Python provides a slice object:
last_three = slice(-3, None)
fruits = ['apple', 'banana', 'cherry', 'date', 'fig', 'grape']
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(fruits[last_three])
# Output: ['date', 'fig', 'grape']
print(nums[last_three])
# Output: [7, 8, 9]
This is particularly useful when the same slice pattern appears in multiple places.
See also:
- Python List Comprehension — another concise way to build and filter lists
- Mastering the ‘in’ Operator — efficient membership testing across sequences