How to Slice Lists in Python

To slice a list in Python, write my_list[start:stop:step]. You get a new list that begins at index start, stops just before stop, and moves step items at a time. Every part is optional, so [:3] means the first three items:

months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
months[:3]    # ['Jan', 'Feb', 'Mar']
months[-2:]   # ['May', 'Jun']

Every output below comes from real runs on Python 3.12.5, with 2026 months, US cities and dollar amounts as the data.

In this tutorial, we’ll slice lists in Python with start, stop and step, negative indexes, safe copies, slice assignment and slice() objects.

How list slicing works: start, stop and step

The stop index is excluded. That’s why months[3:6] has exactly 6 - 3 items, and why [:3] and [3:] split a list cleanly with no overlap:

months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]

print("months[0:3]  ->", months[0:3])     # stop index is NOT included
print("months[:3]   ->", months[:3])      # start defaults to 0
print("months[9:]   ->", months[9:])      # stop defaults to the end
print("months[3:6]  ->", months[3:6])     # Q2 of 2026
print("months[::3]  ->", months[::3])     # every 3rd month

Output:

months[0:3]  -> ['Jan', 'Feb', 'Mar']
months[:3]   -> ['Jan', 'Feb', 'Mar']
months[9:]   -> ['Oct', 'Nov', 'Dec']
months[3:6]  -> ['Apr', 'May', 'Jun']
months[::3]  -> ['Jan', 'Apr', 'Jul', 'Oct']
Command Prompt output of Python slicing a list of months with start, stop and step values
Each slice prints the months it picked; the step of 3 returns January, April, July and October.

Slicing works by position. If you first need to find where an item sits, see getting the index of an element in a Python list.

Slice a list with negative indexes and steps

Negative numbers count from the end: -1 is the last item. A negative step walks backward, so [::-1] returns a reversed copy and leaves the original alone:

sales = [1250.00, 980.50, 1430.25, 1100.00, 1675.80, 1520.40]   # Jan-Jun 2026, USD

print("last 3:      ", sales[-3:])
print("all but last:", sales[:-1])
print("reversed:    ", sales[::-1])
print(f"Q2 total: ${sum(sales[-3:]):,.2f}")

Output:

last 3:       [1100.0, 1675.8, 1520.4]
all but last: [1250.0, 980.5, 1430.25, 1100.0, 1675.8]
reversed:     [1520.4, 1675.8, 1100.0, 1430.25, 980.5, 1250.0]
Q2 total: $4,296.20
Command Prompt output of Python negative list slicing on monthly USD sales, including a reversed copy and a Q2 total
sales[-3:] picks April to June, and their sum prints as the Q2 total in dollars.

For more ways to grab the tail of a list, read getting the last N elements of a list in Python. If you want to flip the list itself instead of making a copy, reversing a list in Python compares reverse(), reversed() and [::-1].

Why doesn’t list slicing raise an IndexError?

Indexing a missing position fails, but slicing quietly clips the bounds to the list’s length. A start past the end just gives you an empty list:

states = ["Texas", "Ohio", "Utah"]

print(states[1:100])    # stop past the end is clipped
print(states[5:10])     # start past the end -> empty list
try:
    print(states[5])    # plain indexing is strict
except IndexError as err:
    print("IndexError:", err)

Output:

['Ohio', 'Utah']
[]
IndexError: list index out of range

That’s handy when a list might be shorter than you expect, but it can hide a bug, so check len() when the size matters.

Copy a list with [:] (and the shallow copy trap)

A full slice, [:], builds a new list. Changing the copy doesn’t touch the original. But it’s a shallow copy, so nested lists inside it are still shared:

cities = ["Austin", "Denver", "Boston"]
backup = cities[:]            # same as cities.copy()
backup.append("Seattle")
print("cities:", cities, "| backup:", backup)

teams = [["Megan", "Alex"], ["Adele", "Lee"]]
shallow = teams[:]
shallow[0].append("Diego")    # inner lists are shared!
print("teams:  ", teams)
print("same inner list?", shallow[0] is teams[0])

Output:

cities: ['Austin', 'Denver', 'Boston'] | backup: ['Austin', 'Denver', 'Boston', 'Seattle']
teams:   [['Megan', 'Alex', 'Diego'], ['Adele', 'Lee']]
same inner list? True
Command Prompt output of a Python list copied with a full slice, then a nested list changed through a shallow copy
Appending to backup leaves cities alone, while the nested team list changes in both because the inner list is shared.

When your data is a list of lists, use copy.deepcopy() for a fully separate copy. My guide to working with a list of lists in Python shows the same trap with nested rows.

Replace, insert and delete items with slice assignment

A slice on the left side of = changes the list in place. The new values can be longer or shorter than the slice, and an empty slice like [2:2] inserts without replacing anything:

orders = [101, 102, 103, 104, 105, 106]

orders[1:3] = [202, 203]          # replace two items
print("replace: ", orders)
orders[1:3] = [7, 8, 9, 10]       # a slice can grow the list
print("grow:    ", orders)
orders[2:2] = [555]               # empty slice = insert
print("insert:  ", orders)
del orders[-2:]                   # delete the last two
print("delete:  ", orders)
orders[::2] = [0, 0, 0, 0]        # extended slice: lengths must match
print("step set:", orders)
try:
    orders[::2] = [1, 2]
except ValueError as err:
    print("ValueError:", err)

Output:

replace:  [101, 202, 203, 104, 105, 106]
grow:     [101, 7, 8, 9, 10, 104, 105, 106]
insert:   [101, 7, 555, 8, 9, 10, 104, 105, 106]
delete:   [101, 7, 555, 8, 9, 10, 104]
step set: [0, 7, 0, 8, 0, 10, 0]
ValueError: attempt to assign sequence of size 2 to extended slice of size 4
Command Prompt output of Python slice assignment replacing, growing, inserting and deleting list items, then a ValueError for an extended slice
Plain slices can grow or shrink the list, but the extended slice [::2] needs exactly as many values as it covers.

del orders[-2:] removes a whole range in one step. To drop a single position, compare the options in removing an element from a list by index in Python.

Reuse slices with slice() objects and itertools.islice

slice() stores a slice as a named value, handy for fixed-width records. islice() slices generators, which don’t support []:

from itertools import islice

row = ["2026-03-14", "Chicago", "IL", "60601", "149.99"]
DATE, PLACE, PRICE = slice(0, 1), slice(1, 4), slice(4, None)
print(row[DATE], row[PLACE], row[PRICE])

squares = (n * n for n in range(1, 1_000_000))   # a generator can't be sliced
print(list(islice(squares, 2, 6)))

Output:

['2026-03-14'] ['Chicago', 'IL', '60601'] ['149.99']
[9, 16, 25, 36]

For other ways to break a list into chunks, see splitting a list in Python. To take the top three records, slice right after sorting a list of objects by attribute.

Python list slicing cheat sheet

SliceWhat you getExample result
a[:3]First three items['Jan', 'Feb', 'Mar']
a[-3:]Last three items['Oct', 'Nov', 'Dec']
a[::2]Every second item['Jan', 'Mar', 'May', ...]
a[::-1]Reversed copy['Dec', 'Nov', ...]
del a[1:3]Removes items 1 and 2List gets shorter in place

If you’re still exploring, these related guides go deeper:

Frequently asked questions

How do I slice a list in Python?

Use my_list[start:stop:step]. The start is included, the stop isn’t, and every part is optional.

How do I get the last 3 items of a list?

Use a negative start: my_list[-3:]. It works even when the list has fewer than three items.

Does slicing change the original list?

No. A slice returns a new list. Only slice assignment or del changes it in place.

Is list[:] a deep copy?

No, it’s shallow. Nested lists stay shared, so use copy.deepcopy() for nested data.

Can a slice go past the end of the list?

Yes. Slicing clips the bounds, so [1:100] never raises IndexError.

Where is list slicing documented?

See common sequence operations in the Python docs.