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: