How to slice a list, string, tuple in Python
In Python, by using a slice (e.g., [2:5:2]
), you can extract subsequences from sequence objects, such as lists, strings, tuples, etc.
Basic usage of slices
[start:stop]
In a slice, the start
and stop
positions for the subsequence are denoted as [start:stop]
. The extracted range is start <= x < stop
, including the item at start
but excluding the item at stop
.
l = [0, 10, 20, 30, 40, 50, 60]
print(l[2:5])
# [20, 30, 40]
Think of the positions (indices) for the slice as pointing between elements.
One way to remember how slices work is to think of the indices as pointing between characters, with the left edge of the first character numbered 0. 3. An Informal Introduction to Python - Strings — Python 3.11.3 documentation
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
This example demonstrates slices for strings, but the same concept applies to lists, tuples, and other sequence objects. The case of negative values is described later.
Omitting start
extracts the subsequence from the beginning, while omitting stop
extracts it to the end. If both are omitted, all items are extracted.
print(l[:3])
# [0, 10, 20]
print(l[3:])
# [30, 40, 50, 60]
print(l[:])
# [0, 10, 20, 30, 40, 50, 60]
Out of range
No error occurs if you specify a position that exceeds the number of items.
print(l[2:10])
# [20, 30, 40, 50, 60]
If no item is selected
No error occurs if you specify start
and stop
that select no item. An empty list is returned.
print(l[5:2])
# []
print(l[2:2])
# []
print(l[10:20])
# []
[start:stop:step]
You can specify step
in addition to start
and stop
as [start:stop:step]. For example, if step
is set to 2
, you can select items at odd-numbered or even-numbered positions.
l = [0, 10, 20, 30, 40, 50, 60]
print(l[::2])
# [0, 20, 40, 60]
print(l[1::2])
# [10, 30, 50]
Other examples:
print(l[::3])
# [0, 30, 60]
print(l[2:5:2])
# [20, 40]
As in the previous examples, if step
is omitted, it is set to 1
.
Extract from the end with a negative value
Negative values for start
and stop
Negative values for start
and stop
represent positions from the end.
The concept of the positions (indices) for the slice is restated below.
+---+---+---+---+---+---+
| P | y | t | h | o | n |
+---+---+---+---+---+---+
0 1 2 3 4 5 6
-6 -5 -4 -3 -2 -1
l = [0, 10, 20, 30, 40, 50, 60]
print(l[3:-1])
# [30, 40, 50]
print(l[-2:])
# [50, 60]
print(l[-5:-2])
# [20, 30, 40]
Negative values for step
If step
is a negative value, the items are selected in reverse order.
Items are selected from the position at start
. Note that if start
does not indicate a position after stop
, the result will be empty.
l = [0, 10, 20, 30, 40, 50, 60]
print(l[5:2:-1])
# [50, 40, 30]
print(l[2:5:-1])
# []
Other examples:
print(l[-2:-5:-1])
# [50, 40, 30]
print(l[-2:2:-1])
# [50, 40, 30]
print(l[5:2:-2])
# [50, 30]
When step
is a negative value, omitting start
selects from the end, and omitting stop
selects to the beginning. If both are omitted, all items are selected.
By omitting start
and stop
and setting step
to -1
, you can get a reversed object.
print(l[:3:-1])
# [60, 50, 40]
print(l[3::-1])
# [30, 20, 10, 0]
print(l[::-1])
# [60, 50, 40, 30, 20, 10, 0]
You can also use reverse()
and reversed()
to reverse lists or strings, tuples, etc. See the following article for details.
Create slice objects with slice()
You can create a slice object using the built-in slice()
function. To repeatedly select the items at the same position, you can create the slice object once and reuse it.
slice(start, stop, step)
is equivalent to start:stop:step
.
l = [0, 10, 20, 30, 40, 50, 60]
sl = slice(2, 5, 2)
print(sl)
# slice(2, 5, 2)
print(type(sl))
# <class 'slice'>
print(l[sl])
# [20, 40]
If two arguments are specified, step
is set to None
. This is equivalent to start:stop
.
sl = slice(2, 5)
print(sl)
# slice(2, 5, None)
print(l[sl])
# [20, 30, 40]
If only one argument is specified, start
and step
are set to None
. This is equivalent to :stop
.
sl = slice(2)
print(sl)
# slice(None, 2, None)
print(l[sl])
# [0, 10]
If all arguments are omitted, a TypeError
is raised. If you want to create a slice object equivalent to :
, explicitly specify None
.
# sl = slice()
# TypeError: slice expected at least 1 arguments, got 0
sl = slice(None)
print(sl)
# slice(None, None, None)
print(l[sl])
# [0, 10, 20, 30, 40, 50, 60]
Assign values using slices
You can assign new values to the range selected by slices.
It does not matter if the number of items in the range selected by slicing does not match the number of items (= the length of object) to be assigned.
l = [0, 10, 20, 30, 40, 50, 60]
l[2:5] = [200, 300, 400]
print(l)
# [0, 10, 200, 300, 400, 50, 60]
l[2:5] = [-2, -3]
print(l)
# [0, 10, -2, -3, 50, 60]
l[2:4] = [2000, 3000, 4000, 5000]
print(l)
# [0, 10, 2000, 3000, 4000, 5000, 50, 60]
l[2:6] = [20000]
print(l)
# [0, 10, 20000, 50, 60]
Note that specifying a scalar value on the right side will result in a TypeError
.
# l[2:3] = 200
# TypeError: can only assign an iterable
l[2:3] = [200]
print(l)
# [0, 10, 200, 50, 60]
If the right side is empty, the elements in the range selected by the slice will be deleted.
l[1:4] = []
print(l)
# [0, 60]
You can also assign an out-of-range or empty range. The value on the right side is inserted at the specified position.
l = [0, 10, 20, 30, 40, 50, 60]
l[100:200] = [-1, -2, -3]
print(l)
# [0, 10, 20, 30, 40, 50, 60, -1, -2, -3]
l[2:2] = [-100]
print(l)
# [0, 10, -100, 20, 30, 40, 50, 60, -1, -2, -3]
If the number of elements is not equal for the range where step
is specified, a ValueError
is raised.
l = [0, 10, 20, 30, 40, 50, 60]
l[1::2] = [100, 200, 300]
print(l)
# [0, 100, 20, 200, 40, 300, 60]
# l[1::2] = [100, 200]
# ValueError: attempt to assign sequence of size 2 to extended slice of size 3
To add an element in the middle or at the end of the list, you can also use the insert()
and append()
methods. See the following article for more information:
- Add an item to a list in Python (append, extend, insert)
- Remove an item from a list in Python (clear, pop, remove, del)
Apply slices to a list of lists
When applying a slice to a list of lists (= 2D list), the inner lists are selected.
l_2d = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
print(l_2d[1:3])
# [[3, 4, 5], [6, 7, 8]]
To apply a slice to the inner lists, use list comprehensions.
print([l[:2] for l in l_2d[1:3]])
# [[3, 4], [6, 7]]
If you want to get a column, you can transpose it.
l_2d_t = [list(x) for x in zip(*l_2d)]
print(l_2d_t)
# [[0, 3, 6, 9], [1, 4, 7, 10], [2, 5, 8, 11]]
print(l_2d_t[1])
# [1, 4, 7, 10]
Note that if you can use NumPy, it is easier to use NumPy to manipulate multi-dimensional arrays. In NumPy, you can specify a slice for each dimension like [1:4, 2:5]
.
Slices make shallow copy
Slicing creates a shallow copy. For more information on shallow and deep copying, see the following article.
For example, when a list consists of immutable objects like numbers, assigning the slicing result to a variable and updating its elements won't affect the original object.
l = [0, 10, 20, 30, 40, 50, 60]
l_slice = l[2:5]
print(l_slice)
# [20, 30, 40]
l_slice[1] = 300
print(l_slice)
# [20, 300, 40]
print(l)
# [0, 10, 20, 30, 40, 50, 60]
When a list contains mutable objects like other lists or dictionaries, updating elements in the copied list will also affect the original list.
l_2d = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
l_2d_slice = l_2d[1:3]
print(l_2d_slice)
# [[3, 4, 5], [6, 7, 8]]
l_2d_slice[0][1] = 400
print(l_2d_slice)
# [[3, 400, 5], [6, 7, 8]]
print(l_2d)
# [[0, 1, 2], [3, 400, 5], [6, 7, 8], [9, 10, 11]]
In the above example, updating the list within the slice also updates the list in the original object. Likewise, updating the list in the original object also affects the list within the slice.
To avoid this, import the copy
module of the standard library and use deepcopy()
.
import copy
l_2d = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
l_2d_slice_deepcopy = copy.deepcopy(l_2d[1:3])
print(l_2d_slice_deepcopy)
# [[3, 4, 5], [6, 7, 8]]
l_2d_slice_deepcopy[0][1] = 400
print(l_2d_slice_deepcopy)
# [[3, 400, 5], [6, 7, 8]]
print(l_2d)
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]
Slices for strings and tuples
Although we have focused on examples using lists so far, slices can also be applied to other sequence objects, such as strings (str
) and tuples.
However, since str
and tuple
are immutable, you cannot assign new values to them.
s = 'abcdefg'
print(s[2:5])
# cde
print(s[::-1])
# gfedcba
# s[2:5] = 'CDE'
# TypeError: 'str' object does not support item assignment
t = (0, 10, 20, 30, 40, 50, 60)
print(t[2:5])
# (20, 30, 40)
# t[2:5] = (200, 300, 400)
# TypeError: 'tuple' object does not support item assignment
See the following article for splitting and replacing strings.