Welcome back to the trail, @name! 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.
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.
1# Expedition trail through the jungle
2expedition_route = ["Base Camp", "River", "Waterfall", "Mountain Peak"]
3
4# Discovered species (order matters - chronology of discoveries!)
5discovered_species = ["Python regius", "Panthera leo", "Loxodonta africana"]
6
7# Temperatures from the last week
8daily_temperatures = [32, 31, 35, 33, 34, 32, 31]
9
10# A list can contain different types
11expedition_data = ["Day 1", 15.5, True, ["Note 1", "Note 2"]]Key characteristics of lists:
1# Empty list - like a clean expedition journal
2empty_path = []
3empty_species = list()
4
5# List with elements
6jungle_animals = ["Tiger", "Elephant", "Monkey", "Parrot"]
7
8# List of numbers
9distances_km = [5, 10, 15, 20, 25]
10
11# List from range()
12numbers = list(range(1, 11)) # [1, 2, 3, ..., 10]
13even_numbers = list(range(0, 21, 2)) # [0, 2, 4, ..., 20]
14
15# Nested lists (list of lists)
16expedition_teams = [
17 ["Darwin", "Alex", "Maya"],
18 ["Sarah", "Tom", "Lisa"],
19 ["Chen", "Ahmed", "Sofia"]
20]In the jungle every place has its position on the map. In Python we use indexes (from 0!).
1animals = ["Tiger", "Elephant", "Monkey", "Parrot", "Python"]
2
3# Indexing from the beginning (0, 1, 2...)
4first_animal = animals[0] # "Tiger"
5second_animal = animals[1] # "Elephant"
6third_animal = animals[2] # "Monkey"
7
8# Indexing from the end (-1, -2, -3...)
9last_animal = animals[-1] # "Python"
10second_last = animals[-2] # "Parrot"
11
12# Index out of range - error!
13# wrong = animals[10] # IndexError!
14
15print(f"First discovered species: {first_animal}")
16print(f"Last discovered species: {last_animal}")Remember: Python indexes from 0, so the first element has index [0], not [1]!
Sometimes you only need a portion of the trail. In Python we use slicing:
1route = ["Start", "Point A", "Point B", "Point C", "Point D", "Finish"]
2
3# Slicing: list[start:stop:step]
4first_three = route[0:3] # ["Start", "Point A", "Point B"]
5middle = route[2:5] # ["Point B", "Point C", "Point D"]
6last_two = route[-2:] # ["Point D", "Finish"]
7all_but_first = route[1:] # From second to end
8all_but_last = route[:-1] # From beginning to second-to-last
9
10# Every other element
11every_second = route[::2] # ["Start", "Point B", "Point D"]
12
13# Reverse the list!
14reversed_route = route[::-1] # ["Finish", "Point D", ..., "Start"]
15
16print(f"First 3 points: {first_three}")
17print(f"Reversed route: {reversed_route}")Slicing syntax: `list[start:stop:step]`
Unlike strings, lists are mutable - you can change them!
1discovered = ["Tiger", "Elephant", "Monkey"]
2
3# Changing a single element
4discovered[1] = "Rhino" # Replacing elephant
5print(discovered) # ["Tiger", "Rhino", "Monkey"]
6
7# Changing a fragment via slicing
8discovered[1:3] = ["Lion", "Cheetah", "Hyena"]
9print(discovered) # ["Tiger", "Lion", "Cheetah", "Hyena"]
10
11# Deleting an element by index
12del discovered[0]
13print(discovered) # ["Lion", "Cheetah", "Hyena"]Python offers many methods for working with lists. Here are the most important ones:
1species = ["Tiger", "Elephant"]
2species.append("Python")
3species.append("Parrot")
4print(species) # ["Tiger", "Elephant", "Python", "Parrot"]
5
6# Analogy: Adding a new discovery to the journal1team1 = ["Darwin", "Alex"]
2team2 = ["Maya", "Sarah"]
3
4team1.extend(team2) # Adds all elements from team2
5print(team1) # ["Darwin", "Alex", "Maya", "Sarah"]
6
7# Note the difference:
8# append adds the ENTIRE list as one element
9# extend adds EACH element from the list1route = ["Start", "Waterfall", "Finish"]
2route.insert(1, "River") # Insert "River" at position 1
3print(route) # ["Start", "River", "Waterfall", "Finish"]1animals = ["Tiger", "Elephant", "Tiger", "Monkey"]
2animals.remove("Tiger") # Removes the FIRST occurrence
3print(animals) # ["Elephant", "Tiger", "Monkey"]
4
5# WARNING: ValueError if the element doesn't exist!1supplies = ["Tent", "Binoculars", "Map", "Compass"]
2
3# Pop without argument - removes the last
4last_item = supplies.pop()
5print(last_item) # "Compass"
6print(supplies) # ["Tent", "Binoculars", "Map"]
7
8# Pop with index
9first_item = supplies.pop(0)
10print(first_item) # "Tent"
11print(supplies) # ["Binoculars", "Map"]1animals = ["Tiger", "Elephant", "Monkey", "Parrot"]
2position = animals.index("Monkey")
3print(position) # 2
4
5# ValueError if not found!
6# pos = animals.index("Lion") # ValueError1temperatures = [30, 32, 30, 35, 30, 33]
2hot_days = temperatures.count(30)
3print(f"Days with temperature 30°C: {hot_days}") # 31distances = [15, 5, 25, 10, 20]
2distances.sort() # Sorts ascending
3print(distances) # [5, 10, 15, 20, 25]
4
5distances.sort(reverse=True) # Descending
6print(distances) # [25, 20, 15, 10, 5]
7
8# Sorting strings (alphabetically)
9animals = ["Zebra", "Antelope", "Lion"]
10animals.sort()
11print(animals) # ["Antelope", "Lion", "Zebra"]1distances = [15, 5, 25, 10, 20]
2sorted_distances = sorted(distances)
3print(distances) # [15, 5, 25, 10, 20] - unchanged!
4print(sorted_distances) # [5, 10, 15, 20, 25] - new listImportant: `.sort()` modifies the list, `sorted()` returns a new one!
1route = ["Start", "A", "B", "Finish"]
2route.reverse()
3print(route) # ["Finish", "B", "A", "Start"]1old_data = [1, 2, 3, 4, 5]
2old_data.clear()
3print(old_data) # []1# Concatenation (joining)
2team1 = ["Darwin", "Alex"]
3team2 = ["Maya", "Tom"]
4full_team = team1 + team2 # ["Darwin", "Alex", "Maya", "Tom"]
5
6# Repetition
7supplies = ["Water"] * 3 # ["Water", "Water", "Water"]
8
9# Checking membership (in, not in)
10animals = ["Tiger", "Elephant", "Monkey"]
11print("Tiger" in animals) # True
12print("Lion" in animals) # False
13print("Python" not in animals) # True
14
15# Length
16num_animals = len(animals) # 3
17
18# Min, Max, Sum (for numbers)
19distances = [5, 10, 15, 20]
20print(min(distances)) # 5
21print(max(distances)) # 20
22print(sum(distances)) # 501# For loop - the most popular way
2animals = ["Tiger", "Elephant", "Monkey"]
3
4for animal in animals:
5 print(f"Discovered: {animal}")
6
7# With index - enumerate()
8for index, animal in enumerate(animals):
9 print(f"{index + 1}. {animal}")
10
11# With index starting from 1
12for index, animal in enumerate(animals, start=1):
13 print(f"{index}. {animal}")
14
15# While loop (less common)
16i = 0
17while i < len(animals):
18 print(animals[i])
19 i += 1We'll talk about this in detail in the next lesson, but here's a quick preview:
1# Traditional way to create a list of squares
2squares = []
3for x in range(1, 6):
4 squares.append(x ** 2)
5# [1, 4, 9, 16, 25]
6
7# List comprehension - shorter and elegant!
8squares = [x ** 2 for x in range(1, 6)]
9# [1, 4, 9, 16, 25]Sometimes you need a "list of lists" - like a map with a coordinate grid:
1# Terrain map (3x3)
2terrain_map = [
3 ["Forest", "River", "Forest"],
4 ["Mountain", "Camp", "Field"],
5 ["Forest", "Forest", "Road"]
6]
7
8# Accessing an element: [row][column]
9center = terrain_map[1][1] # "Camp"
10top_left = terrain_map[0][0] # "Forest"
11
12# Iterating through a 2D list
13for row in terrain_map:
14 for cell in row:
15 print(cell, end=" ")
16 print() # New line after each row1# WARNING - this does NOT copy, it only creates a reference!
2original = ["A", "B", "C"]
3reference = original # Same location in memory!
4
5reference[0] = "X"
6print(original) # ["X", "B", "C"] - changed!
7
8# Proper copying:
9original = ["A", "B", "C"]
10copy1 = original.copy() # copy() method
11copy2 = original[:] # Slicing
12copy3 = list(original) # list()
13
14copy1[0] = "X"
15print(original) # ["A", "B", "C"] - unchanged!
16print(copy1) # ["X", "B", "C"]1# Expedition discovery journal management program
2
3print("=== DISCOVERY JOURNAL ===\n")
4
5# List of discovered species
6discovered_species = []
7
8while True:
9 print("\n1. Add discovery")
10 print("2. Show all discoveries")
11 print("3. Remove discovery")
12 print("4. Search for species")
13 print("5. Exit")
14
15 choice = input("\nChoice: ")
16
17 if choice == "1":
18 species = input("Species name: ")
19 discovered_species.append(species)
20 print(f"✓ Added: {species}")
21
22 elif choice == "2":
23 if len(discovered_species) == 0:
24 print("No discoveries!")
25 else:
26 print(f"\nDiscovered {len(discovered_species)} species:")
27 for i, species in enumerate(discovered_species, 1):
28 print(f"{i}. {species}")
29
30 elif choice == "3":
31 if len(discovered_species) == 0:
32 print("No discoveries to remove!")
33 else:
34 species = input("Name to remove: ")
35 if species in discovered_species:
36 discovered_species.remove(species)
37 print(f"✓ Removed: {species}")
38 else:
39 print("Not found!")
40
41 elif choice == "4":
42 species = input("Search: ")
43 if species in discovered_species:
44 pos = discovered_species.index(species) + 1
45 print(f"✓ Found at position {pos}")
46 else:
47 print("Not found!")
48
49 elif choice == "5":
50 print("\nSee you on the trail!")
51 break
52 else:
53 print("Invalid option!")Create a "Safari Route Planner" program:
In this lesson you learned:
Before moving on:
In the next lesson Darwin will show you dictionaries - a way to catalog discoveries with keys! 🗺️