Chapter 4: Python Collections - Lists, Tuples, and Dictionaries#
In Python, we have several built-in data structures to organize and store multiple pieces of information:
Lists
[]- Ordered, mutable collections (can be changed)Tuples
()- Ordered, immutable collections (cannot be changed)Dictionaries
{}- Collections of key-value pairs
These core data structures form the backbone of Python programming and are essential for writing clear, efficient, and scalable code.
4.1 Lists#
Lists are ordered collections of items that can be changed (mutable). They’re perfect for storing sequences of related data.
Key Characteristics:
Ordered: Items have a specific position (index)
Mutable: You can add, remove, or change items
Allow duplicates: Same value can appear multiple times
Mixed types: Can store different data types together
# A list storing temperatures from an experiment
temperatures = [298.15, 300.10, 299.80]
list_1 = [1,2,3, 4]
list_2 = ['a', 'b', 'c', 'd']
list_3 = [1, 'a', True, [1,2,3]]
type(list_3)
list
# Basic List Examples
print("=== Creating Lists ===")
# Numbers
numbers = [1, 2, 3, 4, 5]
print(f"Numbers: {numbers}")
# Mutation of Lists
numbers[2] = 10
print(f"Mutated Numbers: {numbers}")
# Strings
fruits = ["apple", "banana", "cherry", "date"]
print(f"Fruits: {fruits}")
# Mixed data types
mixed_data = ["hello", 42, 3.14, True]
print(f"Mixed data: {mixed_data}")
# Allow duplicates
measurements = [5.2, 7.1, 5.2, 5.2] # ✓ Same value appears 3 times
print(f"Measurements with duplicates: {measurements}")
# Empty list
empty_list = []
print(f"Empty list: {empty_list}")
=== Creating Lists ===
Numbers: [1, 2, 3, 4, 5]
Mutated Numbers: [1, 2, 10, 4, 5]
Fruits: ['apple', 'banana', 'cherry', 'date']
Mixed data: ['hello', 42, 3.14, True]
Measurements with duplicates: [5.2, 7.1, 5.2, 5.2]
Empty list: []
print(f"\n=== List Properties ===")
print(f"Number of fruits: {len(fruits)}")
print(f"Number of numbers: {len(numbers)}")
print(f"List type: {type(numbers)}")
=== List Properties ===
Number of fruits: 4
Number of numbers: 5
List type: <class 'list'>
4.1.1 List Indexing and Slicing#
Just like strings, lists support indexing and slicing to access individual items or ranges of items.
Indexing:
list[0]- First itemlist[-1]- Last itemlist[i]- Item at position i
print("=== List Indexing ===")
scores = [85, 92, 78, 96, 81]
# 0 1 2 3 4
print(f"Scores: {scores}")
=== List Indexing ===
Scores: [85, 92, 78, 96, 81]
scores[-1]
81
scores = [85, 92, 78, 96, 81]
scores_duplicate = scores.copy()
print(scores_duplicate)
print(scores)
scores[0] = 100 #85
print(scores)
print(scores_duplicate)
[85, 92, 78, 96, 81]
[85, 92, 78, 96, 81]
[100, 92, 78, 96, 81]
[85, 92, 78, 96, 81]
scores = [85, 92, 78, 96, 81]
scores[1] = 100
print(scores)
[85, 100, 78, 96, 81]
print("=== List Indexing ===")
scores = [85, 92, 78, 96, 81]
print(f"Scores: {scores}")
=== List Indexing ===
Scores: [85, 92, 78, 96, 81]
print(f"\n=== Accessing Individual Items ===")
print(f"Highest score: {scores[3]}")
print(f"Lowest score: {scores[2]}")
=== Accessing Individual Items ===
Highest score: 96
Lowest score: 78
# Mutation
scores_duplicate = scores.copy()
print(f"original list: {scores}")
print(f"duplicate list: {scores_duplicate}")
scores_duplicate[1] = 0
print(f"Modified Scores: {scores_duplicate}")
original list: [85, 92, 78, 96, 81]
duplicate list: [85, 92, 78, 96, 81]
Modified Scores: [85, 0, 78, 96, 81]
Slicing:
list[start:end]- Items from start to end-1list[:n]- First n itemslist[n:]- Items from position n to end
scores
[85, 92, 78, 96, 81]
scores[0:2]
[85, 92]
print(f"\n=== List Slicing ===")
print(f"First 3 scores: {scores[:3]}")
print(f"Every other score: {scores[::2]}")
=== List Slicing ===
First 3 scores: [85, 92, 78]
Every other score: [85, 78, 81]
# Calculate average of first 3 scores
first_three = scores[:3]
average = sum(first_three) / len(first_three)
print(f"Average of first 3 scores: {average:.1f}")
Average of first 3 scores: 85.0
4.1.2 List Methods#
Lists have many useful methods for adding, removing, and manipulating data:
Adding Items:
.append(item)- Add item to end.insert(index, item)- Insert item at specific position.extend(iterable)- Add multiple items
numbers = [1, 2, 3]
print(f"Starting list: {numbers}")
numbers.append(4)
print(numbers)
numbers.insert(1, 10)
print(numbers)
numbers.append(5)
numbers.append(6)
numbers.append(7)
numbers.append(8)
# numbers.extend([5,6,7,8])
print(numbers)
Starting list: [1, 2, 3]
[1, 2, 3, 4]
[1, 10, 2, 3, 4]
[1, 10, 2, 3, 4, 5, 6, 7, 8]
# Start with a simple list of numbers
numbers = [1, 2, 3]
print(f"Starting list: {numbers}")
print(f"\n=== Adding Items ===")
# Add single item
numbers.append(4)
print(f"After append: {numbers}")
# Insert at specific position
numbers.insert(1, 10)
print(f"After insert: {numbers}")
# Add multiple items
numbers.extend([5, 6])
print(f"After extend: {numbers}")
Starting list: [1, 2, 3]
=== Adding Items ===
After append: [1, 2, 3, 4]
After insert: [1, 10, 2, 3, 4]
After extend: [1, 10, 2, 3, 4, 5, 6]
Removing Items:
.remove(item)- Remove first occurrence of item.pop()- Remove and return last item.pop(index)- Remove and return item at index
numbers = [1,2,3,4,5,2]
numbers
[1, 2, 3, 4, 5, 2]
numbers.remove(2)
numbers
[1, 3, 4, 5, 2]
last_value = numbers.pop()
print(last_value)
print(numbers)
2
[1, 3, 4, 5]
numbers = [1,2,3,4,5,2]
print(numbers)
numbers.pop(1)
print(numbers)
[1, 2, 3, 4, 5, 2]
[1, 3, 4, 5, 2]
print(f"\n=== Removing Items ===")
# Remove specific value (first occurrence)
numbers.remove(2)
print(f"After removing 2: {numbers}")
# Remove last item
last_item = numbers.pop()
print(f"Removed {last_item}, remaining: {numbers}")
# Remove item at specific index
second_item = numbers.pop(1)
print(f"Removed item at index 1: {second_item}, remaining: {numbers}")
=== Removing Items ===
After removing 2: [1, 3, 4, 5]
Removed 5, remaining: [1, 3, 4]
Removed item at index 1: 3, remaining: [1, 4]
Other Methods:
.count(item)- Count occurrences of item.index(item)- Find index of first occurrence.sort()- Sort list in place.reverse()- Reverse list in place
numbers = [1,1,1,2,2,3,3,3,3]
numbers.count(3)
4
numbers.index(2)
3
numbers = [2,5,10,87,1]
numbers.reverse()
print(numbers)
[1, 87, 10, 5, 2]
print(f"\n=== List Information ===")
# Add some duplicates for counting
numbers.extend([1, 3, 1])
print(f"List with duplicates: {numbers}")
print(f"Count of 1: {numbers.count(1)}")
print(f"Index of 3: {numbers.index(3)}")
print(f"\n=== Sorting and Reversing ===")
print(f"Before sorting: {numbers}")
# Sort in ascending order
numbers.sort()
print(f"After sorting: {numbers}")
# Reverse order
numbers.reverse()
print(f"After reversing: {numbers}")
=== List Information ===
List with duplicates: [1, 87, 10, 5, 2, 1, 3, 1]
Count of 1: 3
Index of 3: 6
=== Sorting and Reversing ===
Before sorting: [1, 87, 10, 5, 2, 1, 3, 1]
After sorting: [1, 1, 1, 2, 3, 5, 10, 87]
After reversing: [87, 10, 5, 3, 2, 1, 1, 1]
4.2 Tuples#
Tuples are ordered collections of items that cannot be changed (immutable). They’re perfect for storing fixed data.
Key Characteristics:
Ordered: Items have a specific position (index)
Immutable: Cannot add, remove, or change items after creation 🔒 🔒 🔒
Allow duplicates: Same value can appear multiple times
Mixed types: Can store different data types together
Faster: More memory efficient than lists for fixed data
When to Use Tuples:
Fixed coordinates or dimensions
Configuration parameters that shouldn’t change
Function return values (multiple values)
Dictionary keys (since they’re immutable)
# A tuple storing fixed simulation parameters
simulation_params = (300.0, 1.0, "NVT") # temperature (K), pressure (atm), ensemble
list_1 = [1,2,3,4]
list_1[1] = 100
list_1
[1, 100, 3, 4]
tuples_1 = (1,2,3,4)
print(tuples_1)
print(type(tuples_1))
print(tuples_1[1])
tuples_1[1] = 100
(1, 2, 3, 4)
<class 'tuple'>
2
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[28], line 7
4 print(type(tuples_1))
6 print(tuples_1[1])
----> 7 tuples_1[1] = 100
TypeError: 'tuple' object does not support item assignment
temperature_range = [100, 200] # min temp, max temp
###
###
temperature_range[0] = 50
###
###
temperature_range[0]
50
point = (10, 20)
print(point[0])
print(point[1])
print(point[-1])
10
20
20
# Basic Tuple Examples
print("=== Creating Tuples ===")
# Coordinates
point = (10, 20)
print(f"Point coordinates: {point}")
# RGB color
color = (255, 0, 128)
print(f"RGB color: {color}")
=== Creating Tuples ===
Point coordinates: (10, 20)
RGB color: (255, 0, 128)
print(f"\n=== Tuple Properties ===")
print(f"Point length: {len(point)}")
print(f"Tuple type: {type(point)}")
print(f"\n=== Accessing Tuple Items ===")
print(f"X coordinate: {point[0]}")
print(f"Y coordinate: {point[1]}")
=== Tuple Properties ===
Point length: 2
Tuple type: <class 'tuple'>
=== Accessing Tuple Items ===
X coordinate: 10
Y coordinate: 20
# Person info
person = ("Alice", 25, "Engineer")
print(f"Person info: {person}")
print(f"Person info length: {len(person)}")
print(f"Name: {person[0]}")
print(f"Age: {person[1]}")
print(f"Job: {person[2]}")
Person info: ('Alice', 25, 'Engineer')
Person info length: 3
Name: Alice
Age: 25
Job: Engineer
print(f"\n=== Tuple Slicing ===")
numbers = (1, 2, 3, 4, 5, 6)
print(f"Numbers: {numbers}")
print(f"First 3: {numbers[:3]}")
print(f"Last 2: {numbers[-2:]}")
print(f"\n=== Single Item Tuples ===")
# Common mistake - this is NOT a tuple!
not_a_tuple = (42)
print(f"not_a_tuple: {not_a_tuple}, type: {type(not_a_tuple)}")
# Correct way - need the comma!
single_tuple = (42,)
print(f"single_tuple: {single_tuple}, type: {type(single_tuple)}")
=== Tuple Slicing ===
Numbers: (1, 2, 3, 4, 5, 6)
First 3: (1, 2, 3)
Last 2: (5, 6)
=== Single Item Tuples ===
not_a_tuple: 42, type: <class 'int'>
single_tuple: (42,), type: <class 'tuple'>
4.2.1 Tuple Immutability#
Immutability means tuples cannot be changed after creation.
What you CANNOT do:
Add items
Remove items
Change existing items
Why is this important?
Because tuples are immutable, they:
Prevent accidental modification
Clearly represent fixed data
Are more memory-efficient than lists
Can be safely used as dictionary keys
print("=== Tuple Immutability ===")
point = (10, 20)
print(f"Original point: {point}")
# Try to modify - this will cause an error!
try:
point[0] = 15 # Try to change x coordinate
except TypeError as e:
print(f"Error: {e}")
print("✓ Confirmed: Tuples cannot be modified!")
point_list = list(point)
point_list[0] = 15
print(f"Modified point: {point_list}")
new_point = tuple(point_list)
print(f"Modified point via list conversion: {new_point}")
=== Tuple Immutability ===
Original point: (10, 20)
Error: 'tuple' object does not support item assignment
✓ Confirmed: Tuples cannot be modified!
Modified point: [15, 20]
Modified point via list conversion: (15, 20)
4.2.2 Tuple Operation#
What you CAN do:
Access items by index
Slice tuples
Count occurrences with
.count()Find index with
.index()Unpack tuples into variables
Tuple Unpacking is a very useful feature that lets you assign tuple values to multiple variables at once.
numbers = (1, 2, 2, 3, 2, 4)
numbers.index(2)
1
print(f"\n=== Tuple Methods ===")
numbers = (1, 2, 2, 3, 2, 4)
print(f"Numbers: {numbers}")
print(f"Count of 2: {numbers.count(2)}")
print(f"Index of 3: {numbers.index(3)}")
=== Tuple Methods ===
Numbers: (1, 2, 2, 3, 2, 4)
Count of 2: 3
Index of 3: 3
# Column headers in a database query result
columns = ("id", "name", "email", "created_at")
email_position = columns.index("email") # Find which column has email
row_data = (123, "Alice", "alice@email.com", "2024-01-01")
email_value = row_data[email_position] # Get email from data row
# CSV header row (often returned as tuple)
headers = ("date", "temperature", "humidity", "pressure")
temp_idx = headers.index("temperature") # Which column is temperature?
Practical Examples#
While tuples are immutable, .count() and .index() are useful for analyzing fixed data structures like database
# Practical Example 1: Working with CSV Database Files
# Reading sensor data from a CSV file
print("=== Example 1: Sensor Data Analysis ===")
print("Scenario: Analyze temperature readings from lab sensors\n")
# Read CSV file (each row becomes a tuple when using certain CSV methods)
with open("sensor_data.csv", "r") as file:
lines = file.readlines()
# Get header (column names) as tuple
header = tuple(lines[0].strip().split(','))
print(f"CSV Columns: {header}")
# Using .index() to find which column contains temperature
temp_column = header.index("temperature")
pressure_column = header.index("pressure")
print(f"Temperature is in column {temp_column}")
print(f"Pressure is in column {pressure_column}")
# Process data rows as tuples
print(f"\n--- Analyzing Data Rows ---")
data_rows = []
for line in lines[1:]:
row_tuple = tuple(line.strip().split(','))
data_rows.append(row_tuple)
# Extract temperatures using the index we found
temperatures = []
for row in data_rows:
temp = float(row[temp_column])
temperatures.append(temp)
print(f"Temperatures: {temperatures}")
# Use .count() to find stable readings
target_temp = 23.5
stable_count = temperatures.count(target_temp)
print(f"\nStable readings at {target_temp}°C: {stable_count} times")
print(f"Percentage of stable readings: {stable_count/len(temperatures)*100:.1f}%")
# Practical Example 2: Student Database Records
print("\n=== Example 2: Student Records Database ===")
print("Scenario: Query student information from database\n")
# Read student records
with open("student_records.csv", "r") as file:
lines = file.readlines()
# Header as tuple
header = tuple(lines[0].strip().split(','))
print(f"Database schema: {header}")
# Using .index() to find column positions (like SQL column lookup)
name_col = header.index("name")
email_col = header.index("email")
major_col = header.index("major")
gpa_col = header.index("gpa")
print(f"\nColumn positions:")
print(f" Name: column {name_col}")
print(f" Email: column {email_col}")
print(f" Major: column {major_col}")
print(f" GPA: column {gpa_col}")
# Process student records as tuples (immutable database rows)
print(f"\n--- Querying Records ---")
students = []
for line in lines[1:]:
student_record = tuple(line.strip().split(','))
students.append(student_record)
# Find Chemical Engineering students using the major column index
print(f"\nChemical Engineering Students:")
chem_eng_count = 0
for student in students:
if student[major_col] == "Chemical Engineering":
print(f" {student[name_col]} - GPA: {student[gpa_col]}")
chem_eng_count += 1
print(f"\nTotal Chemical Engineering students: {chem_eng_count}")
# Extract all majors and count occurrences
majors = [student[major_col] for student in students]
chem_eng_total = majors.count("Chemical Engineering")
print(f"Verified count using .count(): {chem_eng_total}")
4.2.2 Tuple Unpacking#
Tuple unpacking allows you to assign multiple variables at once by extracting values from a tuple in order. This makes code more concise, readable, and less error-prone.
param = (100, 200, 300)
p1, p2, p3 = param
print(p1, p2, p3)
p1 = param[0]
p2 = param[1]
p3 = param[2] # or param[-1]
print(p1, p2, p3)
100 200 300
100 200 300
len(param)
3
p1, p2, p3 = param
def custom_function():
return 100, 200, 300
r1, r2, r3 = custom_function()
print(r1)
print(r2)
print(r3)
# r1 = result[0]
# r2 = result[1]
# r3 = result[2]
100
200
300
print(f"\n=== Tuple Unpacking (Very Useful!) ===")
# Unpack coordinates
point = (100, 200)
x, y = point
print(f"x = {x}, y = {y}")
# Unpack person info
person = ("Bob", 30, "Designer")
name, age, job = person
print(f"Name: {name}, Age: {age}, Job: {job}")
=== Tuple Unpacking (Very Useful!) ===
x = 100, y = 200
Name: Bob, Age: 30, Job: Designer
# Function returning multiple values
def get_name_and_score():
return ("Alice", 95)
student_name, student_score = get_name_and_score()
print(f"Student: {student_name}, Score: {student_score}")
Student: Alice, Score: 95
print(f"\n=== Converting Between Lists and Tuples ===")
# List to tuple
my_list = [1, 2, 3, 4]
my_tuple = tuple(my_list)
print(f"List: {my_list}")
print(f"Tuple: {my_tuple}")
# Tuple to list (if you need to modify)
colors_tuple = ("red", "green", "blue")
colors_list = list(colors_tuple)
colors_list.append("yellow")
print(f"Original tuple: {colors_tuple}")
print(f"Modified list: {colors_list}")
=== Converting Between Lists and Tuples ===
List: [1, 2, 3, 4]
Tuple: (1, 2, 3, 4)
Original tuple: ('red', 'green', 'blue')
Modified list: ['red', 'green', 'blue', 'yellow']
4.3 Dictionaries#
Dictionaries are collections of key-value pairs that are mutable. They’re perfect for storing related information where you need to look up values by a meaningful name (key).
Key Characteristics:
Key-Value pairs: Each item has a key (name) and a value
Mutable: Can add, remove, or change items
Unique keys: Each key can only appear once
Fast lookup: Very efficient for finding values by key
Creating Dictionaries:
# Empty dictionary
data = {}
# Dictionary with values
person = {
"name": "Alice",
"age": 25,
"city": "New York"
}
# Student grades
grades = {
"math": 95,
"science": 87,
"english": 92
}
When to Use Dictionaries:
Storing properties of an object
Looking up values by name instead of position
Counting occurrences of items
Configuration settings
person = {
"name": "Alice",
"age": 25,
"city": "New York"
}
person["name"]
result = person.get("salary", "No key")
print(result)
# person["salary"]
No key
person = ["Alice", 25, "New York", "Engineer"]
person[0]
print(person)
person = {
"name": "Alice",
"age": 25,
"city": "New York",
"job": "Engineer"
}
print(person["name"])
['Alice', 25, 'New York', 'Engineer']
Alice
person = {
"name": "Alice",
"age": 25,
"city": "New York",
"job": "Engineer"
}
# person['salary']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[63], line 8
1 person = {
2 "name": "Alice",
3 "age": 25,
4 "city": "New York",
5 "job": "Engineer"
6 }
----> 8 person['salary']
KeyError: 'salary'
# Person information
person = {
"name": "Alice",
"age": 25,
"city": "New York",
"job": "Engineer"
}
print(f"Person: {person}")
Person: {'name': 'Alice', 'age': 25, 'city': 'New York', 'job': 'Engineer'}
print(f"Name: {person['name']}")
print(f"Age: {person['age']}")
print(f"Person has {len(person)} properties")
Name: Alice
Age: 25
Person has 4 properties
# Compare with direct access
try:
missing = person["salary"] # This key doesn't exist
except KeyError as e:
print(f"Error: Key {e} not found")
print("✓ Use .get() method to avoid errors!")
Error: Key 'salary' not found
✓ Use .get() method to avoid errors!
print(f"\n=== Safe Access with .get() Method ===")
# Using .get() prevents errors if key doesn't exist
job = person.get("job", "Unknown")
salary = person.get("salary", "Not specified")
print(f"Job: {job}")
print(f"Salary: {salary}")
=== Safe Access with .get() Method ===
Job: Engineer
Salary: Not specified
4.3.1 Dictionary Methods and Operations#
Dictionaries have many useful methods for working with key-value pairs:
Adding/Modifying:
dict[key] = value- Add or update a key-value pair.update(other_dict)- Add multiple key-value pairs
Removing:
del dict[key]- Remove key-value pair.pop(key)- Remove and return value.clear()- Remove all items
Accessing:
.keys()- Get all keys.values()- Get all values.items()- Get key-value pairs.get(key, default)- Safe access with default
Checking:
key in dict- Check if key exists
person = {
"name": "Alice",
"age": 25,
"city": "New York",
"job": "Engineer",
}
key_list = list(person.keys())
value_list = list(person.values())
print(key_list)
print(value_list)
value_list[0]
['name', 'age', 'city', 'job']
['Alice', 25, 'New York', 'Engineer']
'Alice'
item_list = list(person.items())
first_name, first_value = item_list[0]
print(first_name, first_value)
name Alice
person = {
"name": "Alice",
"age": 25,
"city": "New York",
"job": "Engineer",
}
person["salary"] = 100_000
print(person)
#del person["salary"]
value = person.pop("salary")
print(value)
person
{'name': 'Alice', 'age': 25, 'city': 'New York', 'job': 'Engineer', 'salary': 100000}
100000
{'name': 'Alice', 'age': 25, 'city': 'New York', 'job': 'Engineer'}
person.keys()
dict_keys(['name', 'age', 'city', 'job'])
person.values()
dict_values(['Alice', 25, 'New York', 'Engineer'])
person.items()
dict_items([('name', 'Alice'), ('age', 25), ('city', 'New York'), ('job', 'Engineer')])
# Dictionary Methods Examples
print("=== Adding and Modifying Items ===")
student = {
"name": "Bob",
"age": 20,
"major": "Computer Science"
}
print(f"Initial: {student}")
# Add new item
student["gpa"] = 3.8
print(f"After adding GPA: {student}")
# Modify existing item
student["age"] = 21
print(f"After birthday: {student}")
# Add multiple items
additional_info = {"year": "Junior", "credits": 75}
student.update(additional_info)
print(f"After update: {student}")
print(f"\n=== Removing Items ===")
# Remove specific item
gpa = student.pop("gpa")
print(f"Removed GPA: {gpa}")
print(f"Remaining: {student}")
# Delete item directly
del student["credits"]
print(f"After deleting credits: {student}")
print(f"\n=== Accessing Dictionary Data ===")
products = {
"laptop": 999,
"mouse": 25,
"keyboard": 75,
"monitor": 300
}
print(f"All products: {list(products.keys())}")
print(f"All prices: {list(products.values())}")
# Iterate through items
print(f"\nPrice list:")
for product, price in products.items():
print(f" {product}: ${price}")
print(f"\n=== Checking for Keys ===")
items_to_check = ["laptop", "tablet", "mouse"]
for item in items_to_check:
if item in products:
print(f"{item}: ${products[item]}")
else:
print(f"{item}: not available")
print(f"\n=== Practical Example: Word Counter ===")
text = "hello world hello python world"
words = text.split()
# Count word occurrences
word_count = {}
for word in words:
if word in word_count:
word_count[word] += 1
else:
word_count[word] = 1
print(f"Word counts: {word_count}")
# Alternative using .get()
word_count2 = {}
for word in words:
word_count2[word] = word_count2.get(word, 0) + 1
print(f"Same result: {word_count2}")
4.4 Choosing the Right Data Structure#
Understanding when to use lists, tuples, or dictionaries:
Data Structure |
When to Use |
Example Use Cases |
|---|---|---|
List |
• Ordered data that changes |
• Shopping list |
Tuple |
• Ordered data that’s fixed |
• GPS coordinates |
Dictionary |
• Need to look up by name |
• Person info |
Decision Flow:
Do you need to look up values by name? → Use Dictionary
Will the data change after creation? → Use List
Is the data fixed/constant? → Use Tuple
# Choosing the Right Data Structure - Examples
print("=== Example 1: Shopping List ===")
print("Scenario: Items you need to buy (order matters, items change)")
# ✅ Correct choice: List (changeable, ordered)
shopping_list = ["bread", "milk", "eggs"]
print(f"Shopping list: {shopping_list}")
# Easy to add/remove items
shopping_list.append("cheese")
shopping_list.remove("eggs")
print(f"Updated list: {shopping_list}")
print(f"\n=== Example 2: GPS Coordinates ===")
print("Scenario: Fixed location coordinates")
# ✅ Correct choice: Tuple (fixed data)
home_location = (40.7128, -74.0060) # New York City
x, y = home_location
print(f"Home coordinates: ({x}, {y})")
print("Coordinates are protected from accidental changes")
print(f"\n=== Example 3: Student Information ===")
print("Scenario: Looking up student data by name")
# ✅ Correct choice: Dictionary (lookup by name)
students = {
"Alice": {"age": 20, "major": "CS", "gpa": 3.8},
"Bob": {"age": 21, "major": "Math", "gpa": 3.5},
"Charlie": {"age": 19, "major": "Physics", "gpa": 3.9}
}
# Easy to look up by name
student = "Alice"
if student in students:
info = students[student]
print(f"{student}: {info['major']} major, GPA: {info['gpa']}")
# Easy to add new students
students["Diana"] = {"age": 20, "major": "Biology", "gpa": 3.7}
print(f"Added Diana. Total students: {len(students)}")
print(f"\n=== Complex Example: Combined Usage ===")
# Store multiple students with courses (using all three structures)
# Dictionary for student lookup
student_db = {}
# Add students with course lists and contact tuples
student_db["John"] = {
"courses": ["Math", "Physics", "Chemistry"], # List - courses change
"contact": ("john@email.com", "555-1234"), # Tuple - fixed contact info
"grades": {"Math": 85, "Physics": 92} # Dict - grade lookup
}
student_db["Mary"] = {
"courses": ["Biology", "Chemistry"],
"contact": ("mary@email.com", "555-5678"),
"grades": {"Biology": 88, "Chemistry": 94}
}
# Display student information
for name, data in student_db.items():
email, phone = data["contact"] # Unpack tuple
courses = ", ".join(data["courses"]) # Join list
avg_grade = sum(data["grades"].values()) / len(data["grades"])
print(f"\n{name}:")
print(f" Email: {email}, Phone: {phone}")
print(f" Courses: {courses}")
print(f" Average grade: {avg_grade:.1f}")
=== Example 1: Shopping List ===
Scenario: Items you need to buy (order matters, items change)
Shopping list: ['bread', 'milk', 'eggs']
Updated list: ['bread', 'milk', 'cheese']
=== Example 2: GPS Coordinates ===
Scenario: Fixed location coordinates
Home coordinates: (40.7128, -74.006)
Coordinates are protected from accidental changes
=== Example 3: Student Information ===
Scenario: Looking up student data by name
Alice: CS major, GPA: 3.8
Added Diana. Total students: 4
=== Complex Example: Combined Usage ===
John:
Email: john@email.com, Phone: 555-1234
Courses: Math, Physics, Chemistry
Average grade: 88.5
Mary:
Email: mary@email.com, Phone: 555-5678
Courses: Biology, Chemistry
Average grade: 91.0
Summary#
In this chapter, you learned about Python’s three main collection data structures:
Lists []#
Ordered and mutable collections
Perfect for sequences of data that change
Use for: shopping lists, scores, measurements
Key methods:
.append(),.remove(),.sort(),.pop()
Tuples ()#
Ordered and immutable collections
Perfect for fixed data like coordinates
Use for: coordinates, constants, return values
Key methods:
.count(),.index(), tuple unpacking
Dictionaries {}#
Key-value pairs, mutable
Perfect for looking up data by name
Use for: person info, settings, word counts
Key methods:
.get(),.keys(),.values(),.items()
Quick Decision Guide#
Need lookup by name? → Dictionary
Data will change? → List
Data is fixed? → Tuple
Practice: Try using these structures in your own programs to get comfortable with when to use each one!