Lists

Learn how to store multiple values in a single variable using lists, and how to add, remove, and access items.

~22 min Beginner

What is a list?

So far each variable has held one value. But often you need a whole collection: student names, prices, scores. A list holds many values in one variable, in order. You create one with square brackets and commas between the items.

fruits = ["apple", "banana", "cherry"]
scores = [95, 87, 72, 61, 98]
mixed = [1, "hello", True, 3.14]  # different types are fine

Without lists, you would need a separate variable for each item (fruit1, fruit2, fruit3 and so on), and that quickly becomes impossible. With a list you keep them together and can loop over them. An empty list is written [] and is the usual starting point when you want to add items later.

shopping = []
print(shopping)   # []

Accessing and changing items

Each item has an index, which is its position number, and the first item is at 0. Use square brackets to reach it:

fruits = ["apple", "banana", "cherry"]

print(fruits[0])   # apple
print(fruits[1])   # banana
print(fruits[2])   # cherry
print(fruits[-1])  # cherry, a negative index counts from the end

Asking for an index that is not there causes an IndexError. With 3 items, the valid indexes are 0, 1 and 2 (and -1, -2, -3).

Unlike strings, lists can be changed. Assign to an index to change an item:

fruits[1] = "mango"
print(fruits)   # ['apple', 'mango', 'cherry']

A list is mutable, which means you can change it after you create it. That is what makes lists so flexible.

Adding and removing

These are the four methods you will use most. Read each comment to see what it does:

fruits = ["apple", "banana"]

fruits.append("cherry")     # add to the end
print(fruits)  # ['apple', 'banana', 'cherry']

fruits.insert(1, "mango")   # insert at position 1
print(fruits)  # ['apple', 'mango', 'banana', 'cherry']

fruits.remove("banana")     # remove by value
print(fruits)  # ['apple', 'mango', 'cherry']

last = fruits.pop()         # remove and return the last item
print(last)     # cherry
print(fruits)   # ['apple', 'mango']
  • append(x) puts x at the end
  • insert(i, x) puts x at position i and pushes the others along
  • remove(x) deletes the first item equal to x, and raises a ValueError if there is none
  • pop() removes the last item and gives it back. pop(0) removes the first

You can also remove by position with del fruits[0], and join two lists with + or extend:

a = [1, 2]
b = [3, 4]
print(a + b)    # [1, 2, 3, 4]
a.extend(b)
print(a)        # [1, 2, 3, 4]

Length and membership

Two quick checks you will do all the time. len() counts the items, and in asks whether an item is in the list:

fruits = ["apple", "banana", "cherry"]

print(len(fruits))          # 3
print("banana" in fruits)   # True
print("grape" in fruits)    # False

There is also not in, which is the opposite. Combine these with if to make decisions:

if "grape" not in fruits:
    fruits.append("grape")
print(fruits)   # ['apple', 'banana', 'cherry', 'grape']

This pattern avoids adding the same item twice. You can use fruits.count("apple") to count how many times something appears, and fruits.index("cherry") to find its position. An empty list has length 0 and counts as false in an if.

Looping through a list

This is one of the most common patterns in Python:

scores = [85, 92, 78, 95, 61]

for score in scores:
    print(score)

Python takes the items one by one. No index is needed. Use enumerate() when you want the index and the value together:

fruits = ["apple", "banana", "cherry"]

for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")

# 0: apple
# 1: banana
# 2: cherry

You can start counting from 1 by passing a start value: enumerate(fruits, 1). Avoid changing a list (adding or removing items) while you loop over it, as that gives confusing results. Build a new list instead.

A typical job for a loop is to calculate something from the items:

scores = [85, 92, 78, 95, 61]
total = 0
for score in scores:
    total += score
average = total / len(scores)
print(average)   # 82.2

Useful list methods

numbers = [3, 1, 4, 1, 5, 9, 2, 6]

numbers.sort()      # sort in place
print(numbers)      # [1, 1, 2, 3, 4, 5, 6, 9]

numbers.reverse()   # reverse in place
print(numbers)      # [9, 6, 5, 4, 3, 2, 1, 1]

print(min(numbers)) # 1
print(max(numbers)) # 9
print(sum(numbers)) # 31

copy = numbers.copy()  # make a copy
numbers.clear()        # remove all items
print(numbers)         # []

Some methods change the list itself, like sort, reverse, append and clear. Others only read it and give you an answer, like min, max, sum and len. Methods that change a list in place return None, so do not write numbers = numbers.sort(), or you will lose your list.

If you want a sorted version without touching the original, use the sorted() function. Both can sort backwards:

nums = [3, 1, 2]
print(sorted(nums))                 # [1, 2, 3]
print(nums)                         # [3, 1, 2], unchanged
nums.sort(reverse=True)
print(nums)                         # [3, 2, 1]

Why copy()? Writing b = a does not make a second list. It gives the same list two names, so changing one changes the other. Use a.copy() when you need a real duplicate.

Slicing and list comprehensions

Slicing works on lists just like on strings. The start is included and the end is not:

numbers = [10, 20, 30, 40, 50]

print(numbers[1:4])  # [20, 30, 40]
print(numbers[:3])   # [10, 20, 30]
print(numbers[2:])   # [30, 40, 50]

A slice always gives a new list, and it never raises an error if you go past the end. A list comprehension is a compact way to build a new list from an existing one. It can replace a for loop:

# The regular way
squares = []
for i in range(1, 6):
    squares.append(i ** 2)

# List comprehension, same result in one line
squares = [i ** 2 for i in range(1, 6)]   # [1, 4, 9, 16, 25]

# With a condition to filter items
evens = [i for i in range(1, 11) if i % 2 == 0]   # [2, 4, 6, 8, 10]

Read it as: "give me i ** 2 for each i in the range". The condition at the end keeps only the items that pass. If a comprehension feels hard to read, use the normal loop. Clear code beats clever code.

Lists inside lists

A list can hold other lists. This is how you store a grid or a table, like rows and columns:

grid = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

print(grid[0])      # [1, 2, 3], the first row
print(grid[1][2])   # 6, row 1, column 2

The first index picks the row, and the second picks the item in that row. Loop through a grid with a nested loop:

for row in grid:
    for value in row:
        print(value, end=" ")
    print()
1 2 3 
4 5 6 
7 8 9 

You will also meet tuples, which look like lists but use round brackets: point = (3, 4). A tuple cannot be changed after it is made, which is useful for values that should stay fixed, like coordinates.

Common mistakes

  • Index out of range. A list of 3 items has no [3]. The last item is [2] or [-1].
  • Counting from 1. The first item is index 0.
  • Saving the result of sort(). It returns None. Call it on its own line.
  • Using b = a to copy. Both names point to the same list. Use a.copy().
  • Removing something that is not there. Check with in first, or remove() raises an error.
a = [1, 2, 3]
b = a            # not a copy!
b.append(4)
print(a)         # [1, 2, 3, 4], a changed too

When something odd happens to a list, print it right before and after the line you suspect. Seeing the real contents usually explains the problem fast.

Key takeaways

  • A list stores many values in order inside square brackets
  • Indexes start at 0, and negative indexes count from the end
  • Lists can be changed: assign to an index, append, insert, remove, pop
  • len() counts items and in checks membership
  • for item in my_list loops over items, and enumerate adds the index
  • sort, reverse and clear change the list. min, max and sum only read it
  • Slices [start:end] and list comprehensions build new lists. Use .copy() for a real copy
Sign up to track your progress Mark lessons as read and pick up where you left off Sign up free to unlock this practice Your first practice lesson is free to try. Create an account to unlock the rest and save your progress