Module 5

Data Structures

Lists, dictionaries, tuples, and sets — the containers that organize your data, with list comprehensions and real-world examples for each.

💡What You'll Build
By the end of this module, you will use all four of Python's core data structures — lists, dictionaries, tuples, and sets — and write list comprehensions that replace entire loops with a single line. You will build a contact book and a grade book that organize real data the way professional Python code does.

The contact list problem

Your phone has a contact list. For each person, you store their name, phone number, email, and maybe a birthday. Now imagine trying to manage 500 contacts using nothing but individual variables:

python
contact1_name = "Alice"
contact1_phone = "555-0101"
contact1_email = "[email protected]"
contact2_name = "Bob"
contact2_phone = "555-0102"
# ... 1,498 more lines

This is insanity. You cannot loop through it. You cannot search it. You cannot sort it. You need a way to organize data — to group related items together and work with them efficiently.

That is what data structures do. They are containers designed for different kinds of data. Choosing the right container is like choosing the right storage for your kitchen: silverware goes in a drawer (ordered slots), spices go on a labeled rack (named slots), and a fruit bowl holds unique items you grab without caring about order.

In Module 4, your functions took single values — one name, one number. But real programs work with collections: a list of 500 students, a dictionary of product prices, a set of unique categories. Python gives you four core data structures, each designed for a different job.

4core data structures in Python

1 lineto create a list comprehension

0indexing starts here (not 1!)

Without Data Structures

  • Hundreds of individual variables
  • Cannot loop through data
  • Cannot search efficiently
  • Cannot sort or filter
  • Code breaks when data grows

With Data Structures

  • One variable holds all the data
  • Loop through with a single for loop
  • Search in one line
  • Sort and filter built in
  • Scales to millions of items

Lists — ordered, changeable collections

A list is an ordered sequence of items. Think of it as a numbered shopping list: item 1, item 2, item 3. You can add items, remove items, rearrange them, and access any item by its position.

python
# Creating lists
fruits = ["apple", "banana", "cherry"]
numbers = [1, 2, 3, 4, 5]
mixed = ["hello", 42, True, 3.14]    # Lists can hold any type
empty = []

# Accessing items (index starts at 0!)
print(fruits[0])    # "apple" (first item)
print(fruits[1])    # "banana" (second item)
print(fruits[-1])   # "cherry" (last item)
⚠️Indexing starts at 0, not 1
The first item in a list is `list[0]`, not `list[1]`. This is true in almost every programming language. Think of it as an offset: "how many positions from the start?" The first item is 0 positions from the start. This will feel wrong for a week, then it will feel natural forever.

Essential list operations

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

# Adding items
fruits.append("date")           # Add to end: ["apple", "banana", "cherry", "date"]
fruits.insert(1, "blueberry")   # Insert at index 1

# Removing items
fruits.remove("banana")         # Remove by value
last = fruits.pop()             # Remove and return last item
del fruits[0]                   # Remove by index

# Useful operations
print(len(fruits))              # Number of items
print("apple" in fruits)        # True/False — is it in the list?
fruits.sort()                   # Sort in place (alphabetical)
fruits.reverse()                # Reverse in place

Slicing — grabbing a piece of a list

python
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(numbers[2:5])     # [2, 3, 4] — index 2 up to (not including) 5
print(numbers[:3])      # [0, 1, 2] — first 3 items
print(numbers[7:])      # [7, 8, 9] — from index 7 to end
print(numbers[::2])     # [0, 2, 4, 6, 8] — every 2nd item

🔒

List Operations

25 XP

Start with this list: ```python scores = [85, 92, 78, 95, 88, 73, 91] ``` Write code that: 1. Adds the score `100` to the end 2. Removes the lowest score (`73`) 3. Sorts the list from highest to lowest 4. Prints the top 3 scores using slicing Expected final output: `[100, 95, 92]` _Hint: `sort(reverse=True)` sorts high-to-low. Slice `[:3]` gets the first 3 items._

Sign in to earn XP

Dictionaries — labeled containers

A dictionary stores data as key-value pairs. Think of it as an actual dictionary: you look up a word (key) to find its definition (value). Or think of it like a contact card: the labels (Name, Phone, Email) are keys, and the actual data is the values.

python
# Creating a dictionary
person = {
    "name": "Alice",
    "age": 30,
    "city": "London",
    "is_student": False
}

# Accessing values by key
print(person["name"])        # "Alice"
print(person.get("age"))     # 30
print(person.get("email", "N/A"))  # "N/A" (default if key missing)

# Adding/updating
person["email"] = "[email protected]"   # Add new key
person["age"] = 31                     # Update existing key

# Removing
del person["is_student"]

When to use a list vs. a dictionary

Use a list when...Use a dictionary when...
Order mattersYou need named access
Items are similar (all scores, all names)Items have different meanings (name, age, email)
You access by positionYou access by label/key
Example: [85, 92, 78, 95]Example: {"math": 85, "english": 92}

Looping through dictionaries

python
person = {"name": "Alice", "age": 30, "city": "London"}

# Loop through keys
for key in person:
    print(key)                   # name, age, city

# Loop through values
for value in person.values():
    print(value)                 # Alice, 30, London

# Loop through both
for key, value in person.items():
    print(f"{key}: {value}")     # name: Alice, age: 30, city: London
🔑Dictionaries power the entire web
JSON — the format that APIs use to send data across the internet — is essentially a dictionary. When you fetch weather data, user profiles, or stock prices from an API, the data arrives as key-value pairs that map directly to Python dictionaries. Mastering dictionaries is not just a Python skill — it is a web development skill.

There Are No Dumb Questions

"What happens if I access a key that does not exist?"

person["email"] raises a KeyError and crashes. Use person.get("email") instead — it returns None if the key is missing, or a default value you specify: person.get("email", "unknown"). Professional Python code almost always uses .get() for safety.

"Can dictionary keys be anything?"

Keys must be immutable (unchangeable) — strings, numbers, tuples, or booleans. You cannot use a list as a key because lists can change. In practice, 99% of dictionary keys are strings.

🔒

Build a Contact Book

25 XP

Create a dictionary called `contacts` that stores 3 people. Each person's name is the key, and the value is another dictionary with their phone and email: ```python contacts = { "Alice": {"phone": "555-0101", "email": "[email protected]"}, # Add Bob and Charlie } ``` Then write code that: 1. Prints Alice's phone number 2. Adds a new contact "Diana" 3. Loops through all contacts and prints each name and phone number _Hint: Nested access: `contacts["Alice"]["phone"]`. Loop: `for name, info in contacts.items()`._

Sign in to earn XP

Tuples — immutable sequences

A tuple is like a list that cannot be changed after creation. Think of it as a sealed envelope — once you put data in, you cannot modify it.

python
# Creating tuples
coordinates = (40.7128, -74.0060)      # New York City lat/long
rgb_red = (255, 0, 0)
single = (42,)                          # Trailing comma for single-item tuple

# Accessing (same as lists)
print(coordinates[0])    # 40.7128
print(coordinates[1])    # -74.0060

# Unpacking
lat, lon = coordinates
print(f"Latitude: {lat}, Longitude: {lon}")

# This will CRASH:
# coordinates[0] = 41.0   # TypeError: tuples do not support assignment

When to use tuples: when data should not change — coordinates, RGB colors, database rows, function return values.

Sets — unique items only

A set is an unordered collection with no duplicates. Think of it as a guest list for a party — each person can only appear once, and there is no assigned seating order.

python
# Creating sets
colors = {"red", "blue", "green"}
numbers = {1, 2, 3, 2, 1}      # Duplicates removed → {1, 2, 3}

# From a list (removes duplicates)
emails = ["[email protected]", "[email protected]", "[email protected]"]
unique_emails = set(emails)     # {"[email protected]", "[email protected]"}

# Set operations
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a & b)    # {3, 4} — intersection (in both)
print(a | b)    # {1, 2, 3, 4, 5, 6} — union (in either)
print(a - b)    # {1, 2} — difference (in a but not b)

List

  • Ordered — items stay in position
  • Allows duplicates
  • Access by index: list[0]
  • Use for sequences

Set

  • Unordered — no guaranteed position
  • No duplicates ever
  • Cannot access by index
  • Use for membership testing

List comprehensions — Python's secret weapon

A list comprehension creates a new list by transforming or filtering an existing one — in a single line. It is one of the features that makes Python code so compact and readable.

python
# Traditional way
squares = []
for x in range(10):
    squares.append(x ** 2)

# List comprehension — same result, one line
squares = [x ** 2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# With a filter
even_squares = [x ** 2 for x in range(10) if x % 2 == 0]
# [0, 4, 16, 36, 64]

# Transform strings
names = ["alice", "bob", "charlie"]
capitalized = [name.capitalize() for name in names]
# ["Alice", "Bob", "Charlie"]

The pattern: [expression for item in iterable if condition]

There Are No Dumb Questions

"When should I use a list comprehension vs. a regular loop?"

Use a comprehension when you are building a new list by transforming or filtering items. Use a regular loop when you are doing something complex (multiple operations, printing, calling functions with side effects). If the comprehension gets longer than about 80 characters, switch to a loop — readability counts.

"Can I make a dictionary comprehension?"

Yes: {key: value for item in iterable}. Example: {name: len(name) for name in names} gives {"alice": 5, "bob": 3, "charlie": 7}. Same pattern, curly braces instead of square brackets.

<classifychallenge xp="25" title="Pick the Right Container" items={["Names of students in enrollment order","A user profile with name, email, and age","A GPS coordinate that must never change","Countries a user has visited (no repeats)","A shopping cart where items get added and removed","The RGB values of a color (255, 128, 0)"]} options={["List","Dictionary","Tuple","Set"]} hint="Lists are for ordered, changeable sequences. Dictionaries are for labeled key-value data. Tuples are for data that should never change (coordinates, colors). Sets are for unique items where order does not matter.">

🔒

List Comprehension Power

50 XP

Write a list comprehension that takes this list of prices and returns only the prices over $10, each discounted by 20%: ```python prices = [5.99, 12.50, 8.75, 24.99, 3.50, 15.00, 9.99, 31.25] # Expected: [10.0, 19.992, 12.0, 25.0] ``` Then write a dictionary comprehension that maps each word to its length: ```python words = ["python", "data", "structure", "list"] # Expected: {"python": 6, "data": 4, "structure": 9, "list": 4} ``` _Hint: `[price * 0.8 for price in prices if price > 10]` and `{word: len(word) for word in words}`._

Sign in to earn XP

Putting it together — a grade book

python
students = [
    {"name": "Alice", "scores": [85, 92, 78, 95]},
    {"name": "Bob", "scores": [72, 68, 81, 77]},
    {"name": "Charlie", "scores": [91, 95, 88, 93]},
]

for student in students:
    name = student["name"]
    scores = student["scores"]
    avg = sum(scores) / len(scores)
    highest = max(scores)
    print(f"{name}: avg={avg:.1f}, highest={highest}")

This uses a list of dictionaries, each containing a list. Real-world data is almost always nested structures like this.

Back to the contact list

Remember those 1,500 lines of individual variables? With a list of dictionaries, the same data fits in a clean, searchable structure:

python
contacts = [
    {"name": "Alice", "phone": "555-0101", "email": "[email protected]"},
    {"name": "Bob", "phone": "555-0102", "email": "[email protected]"},
    # ... 498 more contacts, all searchable, sortable, and filterable
]

Two lines of structure instead of 1,500 lines of chaos. That is the power of choosing the right data structure.

Next up: Your data structures live in memory — when the program ends, the data vanishes. In the next module, you will learn to read and write data to files — CSV spreadsheets, JSON documents, and even live data from web APIs. That is where Python starts solving real-world problems.

Key takeaways

  • Lists are ordered, changeable sequences — use for collections where order matters: [1, 2, 3]
  • Dictionaries are key-value pairs — use for labeled data: {"name": "Alice", "age": 30}
  • Tuples are immutable sequences — use for data that should not change: (40.71, -74.00)
  • Sets are unordered collections with no duplicates — use for membership and uniqueness: {1, 2, 3}
  • Indexing starts at 0 — the first item is list[0], not list[1]
  • Use .get() for dictionary access — avoids crashes when a key is missing
  • List comprehensions create lists in one line: [x * 2 for x in range(10)]
  • Real-world data is nested — lists of dictionaries, dictionaries of lists — get comfortable with it

?

Knowledge Check

1.What does `[1, 2, 3, 2, 1]` become when converted to a set with `set([1, 2, 3, 2, 1])`?

2.Given `d = {"name": "Alice", "age": 30}`, what does `d.get("email", "N/A")` return?

3.What does `[x ** 2 for x in range(5)]` produce?

4.Which data structure is immutable (cannot be changed after creation)?

Want to go deeper?

💻 Software Engineering Master Class

The complete software engineering program — from your first line of code to landing your first job.

View the full program