Python’s list type (part 1) — Indexing and slicing

Tue Nguyen
6 min readApr 15, 2022

--

List type is one the four sequence types that we will learn in this series. The others are tuples, ranges, and strings.

A sequence is a collection of elements sharing the same name. Each element can be access using its position (or index) in the sequence. Python starts indexing at 0, thus if a sequence has N elements, then the elements are indexed by 0, 1, ..., N-1.

In part 1 we will learn how to

  1. Create a list
  2. Index elements of a list
  3. Slice elements of a list

Create a list

To create a list we use []. Elements are separated by commas ,.

x = [1, 2, 3, 4, 5]
print(x)
print(type(x))
[1, 2, 3, 4, 5]
<class 'list'>

Elements of a list can be of different types, even lists themselves.

x = [1, 2.5, "A", True, None, [1, 2]]
print(x)
[1, 2.5, 'A', True, None, [1, 2]]

Index a list

Indexing a list means accessing one single element of a list. There are two type of indexing

  1. Indexing (read): access an element, read its value, but does not modify it
  2. Indexing (write): access an element, then modify it

A. Indexing — read

First, let’s initialize a list x with five elements 1, 2, 3, 4, 5.

x = [1, 2, 3, 4, 5]

We can index a list by counting from left to right (using positive index).

  • 0 means the 1st position
  • 2 means the 3rd position
  • 4 means the 5th position
# 1st element
x[0]
1# 3rd element
x[2]
3# Last element
x[4]
5

We can also index a list by counting from the right to left (using negative index)

  • -1 means the last position
  • -2 means the second-to-last position
# Last element
x[-1]
5# 2nd-to-last element
x[-2]
4

If we try to access outside the range of a list, we will get a list index out of range error. For example, try it yourself with x[5] (index the 6th element while the list x only has 5 elements)

B. Indexing — write

Sometimes we might want to access an element of a list and change change it to a different value. We can do it through indexing and assignment.

# First, intialize a list
x = [1, 2, 3, 4, 5]
print(x)
[1, 2, 3, 4, 5]# Change the third element to 99
x[2] = 99
print(x)
[1, 2, 99, 4, 5]# Change the last element to "Hello"
x[-1] = "Hello"
print(x)
[1, 2, 99, 4, 'Hello']# Change the third element (again) to [40, 50]
x[2] = [40, 50]
print(x)
[1, 2, [40, 50], 4, 'Hello']

Besides indexing an element and modifying it, we can also delete it from the list using del (short for "delete").

# Delete the last element
del x[-1]
print(x)
[1, 2, [40, 50], 4]

Note: be careful when using del to delete multiple elements because after each del, the list is shorter by one element. So you need to adjust the counting accordingly. Let's see an example.

# Here you are trying to delete the 1st and 3rd elements
# i.e., element 1 and [40, 50]
# But after 1st element is deleted,
# the original 3rd element now becomes 2nd element
# so you end up deleting 4 instead of [40, 50]
del x[0], x[2]
print(x)
[2, [40, 50]]

Slice a list

In contrast to indexing, which accesses one single element at a time, slicing accesses a bunch of elements (called a slice) simultaneously.

There are also two type of slicing:

  1. Slicing (read): access a slice, but does not modify it
  2. Slicing (write): access a slice, then modify it

A. Slicing — read

To slice a list, we use the following syntax: x[start:stop:step].

  • x: the name of the list
  • start: starting position (will be included in the result)
  • stop: ending position (will be excluded from the result)
  • step: number of elements between each jump

In many cases, we want a consecutive slice (step = 1). If so, we can use x[start:stop] instead.

Slicing a list is a bit tricky, but you will get used to it through practice. Let’s do it.

# First, initialize a list
x = [1, 2, 3, 4, 5]
x
[1, 2, 3, 4, 5]# Slice from 1st to 3rd
# Since stop is not included,
# to have the 3rd elemnt in the result,
# we have to set stop = 3 (index to the 4th element)
x[0:3]
[1, 2, 3]# If start = 0, we can omit it
x[:3]
[1, 2, 3]# Slice from 3rd element to last
# Here, start is included
# so we set start = 2 (index of 3rd element)
# and since we want to slice to the end
# we can omit stop
x[2:]
[3, 4, 5]# Slice from the beginning to the end
# (create a shallow copy, will discuss later)
x[:]
[1, 2, 3, 4, 5]# Slice from 2nd to 4th
x[1:4]
[2, 3, 4]# Slice last 3 elements
# Here, start = -3 means we start from
# the 3rd element counting from the right
# and slice to the end
x[-3:]
[3, 4, 5]# Slice from 1st to 2nd-to-last
x[:-1]
[1, 2, 3, 4]

Unlike indexing, there will be no out-of-range error if we try to slice beyond the range of the list. Python will try to slice as many elements as available.

x[2:10000][3, 4, 5]

Note that slicing is different from indexing. Indexing returns an element of the list, while slicing returns a list that contain some elements of the original list, for example

# Return the first element
# which is an integer
x[0]
1# Return a list containing only the first element
x[:1]
[1]

B. Slicing — write

Similar to indexing (write), we can slice a list and modify that slice through an assignment.

# Initialize a list again
x = [1, 2, 3, 4, 5]
print(x)
[1, 2, 3, 4, 5]# Replace three first elements with 100, 200, 300
x[:3] = [100, 200, 300]
print(x)
[100, 200, 300, 4, 5]

If we assign to a slice a list that is longer/shorter than the slice’s, then the list will automatically expand/shrink accordingly.

# Replace the first 3 elements to 99, 98
x[:3] = [98, 99]
print(x)
[98, 99, 4, 5]# Replacing the last element with -98, -99
x[-1:] = [-98, -99]
print(x)
[98, 99, 4, -98, -99]

Slicing with steps

If we want a jump different from 1, we need to provide step.

# First, let's initialize a list
x = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(x)
[1, 2, 3, 4, 5, 6, 7, 8, 9]# Slice from 2nd to 7th
# and no skip between jumps
x[1:7]
[2, 3, 4, 5, 6, 7]# Slice from 2nd to 7th
# and skip 1 elements between jumps
x[1:7:2]
[2, 4, 6]# Slice from 2nd to 7th
# and skip 2 elements between jumps
x[1:7:3]
[2, 5]

We can also use a negative step (meaning slicing from right to left). If so, start must be greater than stop.

# Slice from last 7th to 2nd
# no skip
x[6:0:-1]
[7, 6, 5, 4, 3, 2]# Slice from last 7th to first
# no skip
x[6::-1]
[7, 6, 5, 4, 3, 2, 1]# Slice from last to first
# no skip
# (equivalent to reversing the list)
x[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1]# Slice from last to first
# skip 2 elements between jumps
x[::-2]
[9, 7, 5, 3, 1]# If start < stop while using step < 0
# then you will get an empty list
x[1:5:-1]
[]

Navigation

Previous: Python’s real number (float) type
Next: Python’s list type (part 2) — List iteration and mutability

--

--

Tue Nguyen

Former data scientist. MSc student in quantitative economics. Love sharing data science stuff.