Python course ยท Module 2: Data Structures
Lists as Expedition Trails
In this lesson15
Welcome back to the trail! Darwin here with the next stage of our expedition.
In the previous module you learned the basics - variables, data types, functions. Now it's time for something more powerful - data collections. On a real expedition you need to manage many elements at once: a list of places to visit, a catalog of discovered species, equipment supplies. In Python we use lists for this.
What Are Lists?
A list is an ordered collection of elements that can be of different types. Think of it as an expedition trail - a sequence of points that you visit one after another.
# Expedition trail through the jungle
expedition_route = ["Base Camp", "River", "Waterfall", "Mountain Peak"]
# Discovered species (order matters - chronology of discoveries!)
discovered_species = ["Python regius", "Panthera leo", "Loxodonta africana"]
# Temperatures from the last week
daily_temperatures = [32, 31, 35, 33, 34, 32, 31]
# A list can contain different types
expedition_data = ["Day 1", 15.5, True, ["Note 1", "Note 2"]]Key characteristics of lists:
- Ordered - order matters
- Mutable - they can be modified
- Can contain duplicates
- Can contain different data types
- Indexed from 0
Creating Lists
# Empty list - like a clean expedition journal
empty_path = []
empty_species = list()
# List with elements
jungle_animals = ["Tiger", "Elephant", "Monkey", "Parrot"]
# List of numbers
distances_km = [5, 10, 15, 20, 25]
# List from range()
numbers = list(range(1, 11)) # [1, 2, 3, ..., 10]
even_numbers = list(range(0, 21, 2)) # [0, 2, 4, ..., 20]
# Nested lists (list of lists)
expedition_teams = [
["Darwin", "Alex", "Maya"],
["Sarah", "Tom", "Lisa"],
["Chen", "Ahmed", "Sofia"]
]Accessing Elements - Indexing
In the jungle every place has its position on the map. In Python we use indexes (from 0!).
animals = ["Tiger", "Elephant", "Monkey", "Parrot", "Python"]
# Indexing from the beginning (0, 1, 2...)
first_animal = animals[0] # "Tiger"
second_animal = animals[1] # "Elephant"
third_animal = animals[2] # "Monkey"
# Indexing from the end (-1, -2, -3...)
last_animal = animals[-1] # "Python"
second_last = animals[-2] # "Parrot"
# Index out of range - error!
# wrong = animals[10] # IndexError!
print(f"First discovered species: {first_animal}")
print(f"Last discovered species: {last_animal}")Remember: Python indexes from 0, so the first element has index [0], not [1]!
Slicing - Extracting Fragments
Sometimes you only need a portion of the trail. In Python we use slicing:
route = ["Start", "Point A", "Point B", "Point C", "Point D", "Finish"]
# Slicing: list[start:stop:step]
first_three = route[0:3] # ["Start", "Point A", "Point B"]
middle = route[2:5] # ["Point B", "Point C", "Point D"]
last_two = route[-2:] # ["Point D", "Finish"]
all_but_first = route[1:] # From second to end
all_but_last = route[:-1] # From beginning to second-to-last
# Every other element
every_second = route[::2] # ["Start", "Point B", "Point D"]
# Reverse the list!
reversed_route = route[::-1] # ["Finish", "Point D", ..., "Start"]
print(f"First 3 points: {first_three}")
print(f"Reversed route: {reversed_route}")Slicing syntax: list[start:stop:step]
start- from which index (inclusive)stop- up to which index (NOT inclusive!)step- step size (default 1)
Modifying Lists
Unlike strings, lists are mutable - you can change them!
discovered = ["Tiger", "Elephant", "Monkey"]
# Changing a single element
discovered[1] = "Rhino" # Replacing elephant
print(discovered) # ['Tiger', 'Rhino', 'Monkey']
# Changing a fragment via slicing
discovered[1:3] = ["Lion", "Cheetah", "Hyena"]
print(discovered) # ['Tiger', 'Lion', 'Cheetah', 'Hyena']
# Deleting an element by index
del discovered[0]
print(discovered) # ['Lion', 'Cheetah', 'Hyena']List Methods - Exploration Tools
Python offers many methods for working with lists. Here are the most important ones:
append() - add to end
species = ["Tiger", "Elephant"]
species.append("Python")
species.append("Parrot")
print(species) # ['Tiger', 'Elephant', 'Python', 'Parrot']
# Analogy: Adding a new discovery to the journalextend() - extend the list
team1 = ["Darwin", "Alex"]
team2 = ["Maya", "Sarah"]
team1.extend(team2) # Adds all elements from team2
print(team1) # ['Darwin', 'Alex', 'Maya', 'Sarah']
# Note the difference:
# append adds the ENTIRE list as one element
# extend adds EACH element from the listinsert() - insert at a specific position
route = ["Start", "Waterfall", "Finish"]
route.insert(1, "River") # Insert "River" at position 1
print(route) # ['Start', 'River', 'Waterfall', 'Finish']remove() - remove a value
animals = ["Tiger", "Elephant", "Tiger", "Monkey"]
animals.remove("Tiger") # Removes the FIRST occurrence
print(animals) # ['Elephant', 'Tiger', 'Monkey']
# WARNING: ValueError if the element doesn't exist!pop() - remove and return an element
supplies = ["Tent", "Binoculars", "Map", "Compass"]
# Pop without argument - removes the last
last_item = supplies.pop()
print(last_item) # Compass
print(supplies) # ['Tent', 'Binoculars', 'Map']
# Pop with index
first_item = supplies.pop(0)
print(first_item) # Tent
print(supplies) # ['Binoculars', 'Map']index() - find an element's position
animals = ["Tiger", "Elephant", "Monkey", "Parrot"]
position = animals.index("Monkey")
print(position) # 2
# ValueError if not found!
# pos = animals.index("Lion") # ValueErrorcount() - count occurrences
temperatures = [30, 32, 30, 35, 30, 33]
hot_days = temperatures.count(30)
print(f"Days with temperature 30ยฐC: {hot_days}") # 3sort() - sort (modifies the original list!)
distances = [15, 5, 25, 10, 20]
distances.sort() # Sorts ascending
print(distances) # [5, 10, 15, 20, 25]
distances.sort(reverse=True) # Descending
print(distances) # [25, 20, 15, 10, 5]
# Sorting strings (alphabetically)
animals = ["Zebra", "Antelope", "Lion"]
animals.sort()
print(animals) # ['Antelope', 'Lion', 'Zebra']sorted() - return a sorted copy (does NOT modify the original!)
distances = [15, 5, 25, 10, 20]
sorted_distances = sorted(distances)
print(distances) # [15, 5, 25, 10, 20] - unchanged!
print(sorted_distances) # [5, 10, 15, 20, 25] - new listImportant: .sort() modifies the list, sorted() returns a new one!
reverse() - reverse the list
route = ["Start", "A", "B", "Finish"]
route.reverse()
print(route) # ['Finish', 'B', 'A', 'Start']clear() - clear the entire list
old_data = [1, 2, 3, 4, 5]
old_data.clear()
print(old_data) # []Operations on Lists
# Concatenation (joining)
team1 = ["Darwin", "Alex"]
team2 = ["Maya", "Tom"]
full_team = team1 + team2 # ["Darwin", "Alex", "Maya", "Tom"]
# Repetition
supplies = ["Water"] * 3 # ["Water", "Water", "Water"]
# Checking membership (in, not in)
animals = ["Tiger", "Elephant", "Monkey"]
print("Tiger" in animals) # True
print("Lion" in animals) # False
print("Python" not in animals) # True
# Length
num_animals = len(animals) # 3
# Min, Max, Sum (for numbers)
distances = [5, 10, 15, 20]
print(min(distances)) # 5
print(max(distances)) # 20
print(sum(distances)) # 50Iterating Through Lists
# For loop - the most popular way
animals = ["Tiger", "Elephant", "Monkey"]
for animal in animals:
print(f"Discovered: {animal}")
# With index - enumerate()
for index, animal in enumerate(animals):
print(f"{index + 1}. {animal}")
# With index starting from 1
for index, animal in enumerate(animals, start=1):
print(f"{index}. {animal}")
# While loop (less common)
i = 0
while i < len(animals):
print(animals[i])
i += 1List Comprehensions - Preview
We'll cover them in detail in the lesson on list comprehensions, but here's a quick preview:
# Traditional way to create a list of squares
squares = []
for x in range(1, 6):
squares.append(x ** 2)
# [1, 4, 9, 16, 25]
# List comprehension - shorter and elegant!
squares = [x ** 2 for x in range(1, 6)]
# [1, 4, 9, 16, 25]Nested Lists (2D Lists)
Sometimes you need a "list of lists" - like a map with a coordinate grid:
# Terrain map (3x3)
terrain_map = [
["Forest", "River", "Forest"],
["Mountain", "Camp", "Field"],
["Forest", "Forest", "Road"]
]
# Accessing an element: [row][column]
center = terrain_map[1][1] # "Camp"
top_left = terrain_map[0][0] # "Forest"
# Iterating through a 2D list
for row in terrain_map:
for cell in row:
print(cell, end=" ")
print() # New line after each rowCopying Lists - A Trap!
# WARNING - this does NOT copy, it only creates a reference!
original = ["A", "B", "C"]
reference = original # Same location in memory!
reference[0] = "X"
print(original) # ['X', 'B', 'C'] - changed!
# Proper copying:
original = ["A", "B", "C"]
copy1 = original.copy() # copy() method
copy2 = original[:] # Slicing
copy3 = list(original) # list()
copy1[0] = "X"
print(original) # ['A', 'B', 'C'] - unchanged!
print(copy1) # ['X', 'B', 'C']Practical Example - Discovery Journal
# Expedition discovery journal management program
print("=== DISCOVERY JOURNAL ===\n")
# List of discovered species
discovered_species = []
while True:
print("\n1. Add discovery")
print("2. Show all discoveries")
print("3. Remove discovery")
print("4. Search for species")
print("5. Exit")
choice = input("\nChoice: ")
if choice == "1":
species = input("Species name: ")
discovered_species.append(species)
print(f"Added: {species}")
elif choice == "2":
if len(discovered_species) == 0:
print("No discoveries!")
else:
print(f"\nDiscovered {len(discovered_species)} species:")
for i, species in enumerate(discovered_species, 1):
print(f"{i}. {species}")
elif choice == "3":
if len(discovered_species) == 0:
print("No discoveries to remove!")
else:
species = input("Name to remove: ")
if species in discovered_species:
discovered_species.remove(species)
print(f"Removed: {species}")
else:
print("Not found!")
elif choice == "4":
species = input("Search: ")
if species in discovered_species:
pos = discovered_species.index(species) + 1
print(f"Found at position {pos}")
else:
print("Not found!")
elif choice == "5":
print("\nSee you on the trail!")
break
else:
print("Invalid option!")Practical Exercise
The editor holds the list safari_animals. Complete the code:
- Extend the list to at least 5 animals
- Print the number of animals with
len() - Create an empty list
new_animalsand add 2 animals to it withappend()
Code for this lesson: main.py
# Creating a list of safari animals
# Lists store multiple elements in a single variable
# TODO: Create a list with at least 5 safari animals
safari_animals = ["lion", "zebra", "elephant"]
# Display the list
print("Safari animals:")
print(safari_animals)
# TODO: Display the number of animals using len()
print(f"Number of animals: {len(safari_animals)}")
# TODO: Create an empty list and add 2 animals to it
new_animals = []
# Use .append() to add animals
Summary
In this lesson you learned:
- What lists are and how to create them
- Indexing and slicing
- Modifying lists
- List methods: append, extend, insert, remove, pop, sort, reverse
- Operations: concatenation, repetition, in/not in
- Iterating through lists
- Nested lists
- Copying lists (the proper way!)
Checkpoint
Before moving on:
- You understand the difference between indexing and slicing
- You can use at least 5 list methods
- You know the difference between .sort() and sorted()
- You know how to properly copy a list
- You can iterate through a list with enumerate()
In the next lesson Darwin will show you more list methods, and then dictionaries - a way to catalog discoveries with keys!
Docs entries used in this lesson
Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. A list in Python is:
2. What is the index of the first element in a Python list?
3. How do you access the last element of the list 'animals'?
4. What will this return: ['A', 'B', 'C', 'D'][1:3]?
Hands-on tasks in the game
- Vertical ordering
Arrange the program steps in order:
- Code editor
Create a list called 'species' containing: 'Tiger', 'Elephant', 'Parrot'
- Code editor
Print the second element of the list animals = ['Python', 'Gorilla', 'Crocodile']
- Code editor
Slice the first 3 elements of the list route = ['Start', 'A', 'B', 'C', 'D', 'Finish'] (slicing [:3]), store them in the variable first_three and print it
- Horizontal ordering
Arrange the elements to create a list: animals = ['Tiger', 'Elephant']
- Horizontal ordering
Arrange: print(animals[0])
- Vertical ordering
Arrange the steps for creating and displaying a list: