Step 06 of 10
Lists & dictionaries
Store collections of values in lists and dictionaries, loop over them, and model real data such as a shopping cart or a word count.
Real programs rarely deal with one value at a time. A shopping cart has many items, a class has many students, a text has many words. Python's two workhorse collections handle almost all of this: the list, an ordered sequence of values, and the dictionary, which looks values up by a key. This lesson teaches both, the everyday operations on each, and how to combine them to model real data.
Lists: ordered collections
A list holds values in order, inside square brackets:
fruits = ["apple", "banana", "cherry"]
scores = [88, 92, 75, 100]
empty = []
print(len(fruits)) # 3
print(fruits[0]) # apple (indexes start at 0)
print(fruits[-1]) # cherry (negative counts from the end)
print(scores[1:3]) # [92, 75] slicing works like strings
print("banana" in fruits) # TrueUnlike strings, lists are mutable: you can change them in place.
fruits[0] = "apricot" # replace an item
fruits.append("date") # add to the end
fruits.insert(1, "blueberry") # insert at a position
fruits.remove("banana") # remove the first matching value
last = fruits.pop() # remove and return the last item
print(fruits) # ['apricot', 'blueberry', 'cherry']
print(last) # dateAsking for an index that doesn't exist is an error, not an empty answer:
fruits[10] # IndexError: list index out of rangeLooping over lists
A for loop visits each item in order, which is how you'll process lists nearly every time:
prices = [4.99, 12.50, 3.25]
total = 0
for price in prices:
total += price
print(f"Total: ${total:.2f}") # Total: $20.74When you need the position as well, use enumerate, which gives you pairs of (index, item):
for position, fruit in enumerate(["apple", "banana", "cherry"], start=1):
print(f"{position}. {fruit}")1. apple
2. banana
3. cherryPython has built-ins for the common calculations, so you often don't need a loop at all:
scores = [88, 92, 75, 100]
print(sum(scores), min(scores), max(scores)) # 355 75 100
print(sum(scores) / len(scores)) # 88.75
print(sorted(scores)) # [75, 88, 92, 100] a new sorted list
scores.sort(reverse=True) # sorts the list itself, largest first
print(scores) # [100, 92, 88, 75]sorted(x) returns a new list and leaves x alone; x.sort() changes x and returns None. Mixing them up (scores = scores.sort()) is a classic bug that leaves you with None.
Building a new list from an old one
A very common job is "make a list of X from a list of Y". The loop version:
names = ["ana", "ben", "cy"]
capitalised = []
for name in names:
capitalised.append(name.capitalize())Python has a compact form for exactly this, a list comprehension:
capitalised = [name.capitalize() for name in names] # ['Ana', 'Ben', 'Cy']
passed = [s for s in [88, 45, 92, 51] if s >= 50] # [88, 92, 51]Read it as "the list of name.capitalize() for each name in names". Use comprehensions for simple transformations and filters; switch back to a loop when it gets complicated.
Dictionaries: looking things up by key
A list finds items by position. Often you want to find them by a name instead: a phone number by person, a price by product. A dictionary (dict) stores key–value pairs in curly braces:
prices = {"apple": 0.50, "bread": 2.20, "milk": 1.10}
print(prices["bread"]) # 2.2
prices["eggs"] = 3.00 # add a new pair
prices["milk"] = 1.25 # change an existing value
del prices["apple"] # remove a pair
print("milk" in prices) # True (checks keys, not values)
print(len(prices)) # 3Looking up a key that doesn't exist raises a KeyError. When a key might be missing, use .get, which returns a default instead:
print(prices.get("cheese")) # None
print(prices.get("cheese", 0)) # 0Keys must be unique (assigning to an existing key replaces its value) and are usually strings or numbers. Values can be anything, including lists and other dictionaries.
Loop over a dictionary's pairs with .items():
for item, price in prices.items():
print(f"{item:<8} ${price:.2f}")bread $2.20
milk $1.25
eggs $3.00Dictionaries remember the order in which keys were added.
The counting pattern
Counting how often things occur is one of the most common uses of a dictionary:
votes = ["red", "blue", "red", "green", "red", "blue"]
counts = {}
for colour in votes:
counts[colour] = counts.get(colour, 0) + 1
print(counts) # {'red': 3, 'blue': 2, 'green': 1}For each vote, look up the current count (0 if this is the first time), add one, and store it back.
Tuples and sets, briefly
Two more collections you'll meet:
- A tuple is like a list that can't be changed, written with parentheses:
point = (3, 4). Use it for small fixed groups of values, such as coordinates or a function returning two things (return total, count). You can unpack it:x, y = point. - A set holds unique values with no order:
{"red", "blue"}. Adding a duplicate does nothing, and checking membership withinis very fast.set(votes)gives you the distinct values of a list.
Modelling real data: combining collections
Real data is usually a list of records, and each record is a dictionary:
cart = [
{"name": "Notebook", "price": 3.50, "quantity": 4},
{"name": "Pen", "price": 1.20, "quantity": 10},
{"name": "Backpack", "price": 35.00, "quantity": 1},
]
total = 0
for item in cart:
line_total = item["price"] * item["quantity"]
total += line_total
print(f"{item['name']:<10} {item['quantity']:>3} × ${item['price']:>6.2f} = ${line_total:>6.2f}")
print(f"{'Total':<29} ${total:>6.2f}")Notebook 4 × $ 3.50 = $ 14.00
Pen 10 × $ 1.20 = $ 12.00
Backpack 1 × $ 35.00 = $ 35.00
Total $ 61.00This shape, a list of dictionaries, is exactly what you'll get from files, spreadsheets and web APIs later on, so it's worth getting comfortable with now. Inside an f-string that uses double quotes, use single quotes for dictionary keys, as above.
One trap: two names, one list
Assigning a list to a second variable doesn't copy it. Both names refer to the same list:
original = [1, 2, 3]
alias = original
alias.append(4)
print(original) # [1, 2, 3, 4] surprise!To get an independent copy, ask for one:
copy = original.copy() # or list(original), or original[:]
copy.append(5)
print(original) # [1, 2, 3, 4] unchangedThe same applies when you pass a list into a function: the function receives the same list, so if it calls .append the caller sees the change. Usually that's what you want; just be aware of it.
Practice
Write wordcount.py that analyses a piece of text:
- Store a paragraph of text in a variable (paste anything you like, a few sentences long).
- Split it into words with
text.lower().split(), and remove punctuation from each word withword.strip(".,!?;:\"'()"). Skip any word that becomes empty. - Count how often each word appears, using a dictionary.
- Print the total number of words, the number of distinct words, and the 5 most common words with their counts.
For step 4, this sorts a dictionary's pairs by count, highest first: sorted(counts.items(), key=lambda pair: pair[1], reverse=True). The key= part tells sorted what to compare: here, the second element of each pair.
Show solution
# wordcount.py
text = """The quick brown fox jumps over the lazy dog. The dog sleeps,
and the fox runs away. A quick fox is a happy fox!"""
counts = {}
total = 0
for raw in text.lower().split():
word = raw.strip(".,!?;:\"'()")
if not word:
continue
total += 1
counts[word] = counts.get(word, 0) + 1
print(f"Total words: {total}")
print(f"Distinct words: {len(counts)}")
print("Most common:")
ranked = sorted(counts.items(), key=lambda pair: pair[1], reverse=True)
for word, count in ranked[:5]:
print(f" {word:<8} {count}")Total words: 24
Distinct words: 15
Most common:
the 4
fox 4
quick 2
dog 2
a 2split() with no argument splits on any whitespace, including line breaks. if not word skips strings that became empty after stripping (an empty string counts as false). ranked[:5] slices the first five pairs, and each pair unpacks into word, count in the loop. When two words have the same count, sorted keeps them in the order they first appeared, because Python's sort is stable.
Key takeaways
- A list is an ordered, changeable sequence: index from 0,
append,insert,remove,pop, and loop withfororenumerate. sorted()returns a new list;.sort()changes the list and returnsNone.- A dictionary maps unique keys to values: look up with
d[key]ord.get(key, default), loop with.items(). counts[k] = counts.get(k, 0) + 1is the counting pattern; a list of dictionaries is the standard shape for records.- Assigning a list to another name doesn't copy it; use
.copy()when you need an independent list.
Check yourself
Quiz
0/4 correct · 4 left
1.numbers = [5, 3, 8]; result = numbers.sort(). What is result?
2.stock = {"pens": 10}. Which expression returns 0 instead of raising an error for a missing key?
3.a = [1, 2]; b = a; b.append(3); print(a). What is printed?
4.You need to look up a student's grade quickly by their student ID. Which collection fits best?
Finished reading?
Mark it complete to fill in your roadmap.