Lists
Ordered, changeable collections
In this lesson
Explain it like I’m 5
A list is like a numbered row of boxes. Each box holds one thing, you can look in any box by its number, and you can add or remove boxes whenever you like.
Creating and reading lists
Write a list with square brackets and commas: colors = ["red", "green", "blue"]. Each item has a position called an index, starting at 0. So colors[0] is ‘red’ and colors[2] is ‘blue’. Negative indexes count from the end: colors[-1] is the last item.
colors = ["red", "green", "blue"]
print(colors[0])
print(colors[2])
print(colors[-1])
red blue blue
Slicing: grabbing a piece
A slice copies a range of items: colors[0:2] gives the first two (start included, stop excluded — the same rule as range). You can omit either end: colors[:2] from the start, colors[1:] to the end. Slicing always returns a new list, leaving the original untouched.
letters = ["a", "b", "c", "d", "e"]
print(letters[1:4])
print(letters[:2])
print(letters[-2:])
['b', 'c', 'd'] ['a', 'b'] ['d', 'e']
Lists are mutable: changing them in place
Lists are mutable — you can change them after creating them. colors[0] = "crimson" replaces an item. .append(x) adds to the end, .insert(i, x) adds at a position, .remove(x) deletes the first matching value, and .pop() removes and returns the last item. These methods change the list itself rather than making a copy.
scores = [40, 90, 65]
scores.append(78)
scores.sort()
print(scores)
print("Highest:", scores[-1])
print("How many:", len(scores))
[40, 65, 78, 90] Highest: 90 How many: 4
Add 'grape' to the shopping list, remove 'milk', then print the final list and its length.
shopping = ["bread", "milk", "eggs"]
# add grape, remove milk
print(shopping)
print("Items:", len(shopping))
Use shopping.append("grape") and shopping.remove("milk") before printing.
shopping = ["bread", "milk", "eggs"]
shopping.append("grape")
shopping.remove("milk")
print(shopping)
print("Items:", len(shopping))
['bread', 'eggs', 'grape']
Items: 3
Useful list operations
len(colors) gives the count. x in colors tests membership. .sort() orders the list in place; sorted(colors) returns a sorted copy. Looping is natural: for color in colors: visits each item in order. Because lists keep their order, the items always come out the way you put them in.
nums = [3, 1, 2]
print(len(nums))
print(2 in nums)
print(sorted(nums))
print(nums)
3 True [1, 2, 3] [3, 1, 2]
Copying a list (and the sharing gotcha)
Here’s a trap that catches everyone once. b = a does not copy a list — it just gives the same list a second name. Change one and you change both, because they’re the very same object in memory.
To get an independent copy, use a.copy() or a full slice a[:]. This only matters because lists are mutable; immutable tuples can’t be changed, so sharing them is harmless. (To build a new list by transforming an old one, see list comprehensions.)
a = [1, 2, 3]
b = a # same list, two names
b.append(4)
print(a) # a changed too!
c = a.copy() # an independent copy
c.append(99)
print(a) # a is untouched
[1, 2, 3, 4] [1, 2, 3, 4]
Common mistake: IndexError: list index out of range
Because indexes start at 0, the last valid index is len(list) - 1. Asking for an index equal to or beyond the length fails.
Use list[-1] for the last item, and remember a list of N items has indexes 0 to N−1.
Common mistake: Expecting .sort() to return the sorted list
.sort() changes the list in place and returns None, so x = mylist.sort() leaves x as None.
Either call mylist.sort() and then use mylist, or use sorted(mylist) which returns a new sorted list.
What is the index of the first item in a list?
Python lists are zero-indexed: the first item is at index 0.
What does scores[-1] refer to?
Negative indexes count from the end, so -1 is the last item.
Mini exercise (medium)
Given nums = [5, 3, 8, 1, 9, 2], print the two largest numbers without removing anything from the original list.
Do it here. Finish the code below and press Run to try your answer right in the browser — no setup needed.
nums = [5, 3, 8, 1, 9, 2]
top_two = [] # TODO: the two largest, without changing nums
print(top_two)
sorted(nums) returns a sorted copy; take the last two with a slice.
nums = [5, 3, 8, 1, 9, 2]
top_two = sorted(nums)[-2:]
print(top_two)
[8, 9]
__no_output_bypass__ = True
import ast as _ast
_tree = _ast.parse(__user_code__)
_names = [n.id for n in _ast.walk(_tree) if isinstance(n, _ast.Name)]
_attrs = [n.attr for n in _ast.walk(_tree) if isinstance(n, _ast.Attribute)]
assert "sorted" in _names or "sort" in _attrs, "use sorted() or .sort() to order the list"
__no_output_bypass__ = False
assert sorted(top_two) == [8, 9], "should be the two largest"
assert nums == [5, 3, 8, 1, 9, 2], "leave the original list unchanged"
print("✓ Correct!")