Skip to main content

Section 3.1 Lists

135 minutes
We use lists every day to keep track of things, for example, shopping lists, to-do lists, or song playlists. Python makes it easy to work with lists. In this topic, we will learn to use lists to store values, manipulate list contents, and traverse lists with loops.

Subsection 3.1.1 Lists as Data Collections

All programming languages have ways to store collections of data. Python has a built-in data type called a list which can store an ordered sequence of items. Lists are sometimes called arrays in other programming languages.
You can imagine a list as a row of lockers where each locker holds one item or element. The lockers are numbered with an index that starts at 0 for the first locker, 1 for the second locker, and so on.
Here are some examples of lists in Python. Notice how square brackers [] are used to collect multiple values to store in one list variable. Instead of using many variables like score1, score2, etc., which would get unmanageable pretty quickly, you can use a single list variable like scores or shopping_list to store a collection of values.
# A shopping list
shopping_list = ["milk", "eggs", "bread", "butter"]
# A list of scores
scores = [95, 87, 92, 100]

Subsection 3.1.2 Index to Access Elements

To access elements in a list, we use the list name and the index (the position or number) of the element in square brackets. For example, shopping_list[0] accesses the first element in the shopping_list, which is "milk". Most programming languages, including Python, use zero-based indexing where the first item in the list is at index 0. Just like binary code, computers almost always start counting at 0.
Note that the AP CSP exam currently starts indexing at 1 in its pseudocode including in the 2027 exam, but will switch to zero-based indexing as of 2028.
Imagine a Python list called lockers. Let’s put your books in locker 0 and a backpack in locker 1 with the code below. To get to a specific locker or a specific element in a list, use the list name followed by square brackets and the index (number) of the element you want to access like below.
lockers[0] = "books"
lockers[1] = "backpack"
print("What's in locker 0?", lockers[0] )
print("What's in locker 1?", lockers[1] )
Let’s try it below:

Activity 3.1.1.

Using the lockers list below, print what is in the first and last locker using the list name and the index in square brackets, for example: lockers[0].

Subsection 3.1.3 Unplugged Activity: List of Chairs

Project 3.1.2. Unplugged List of Chairs.

In groups or as a class, simulate a list using students in chairs. Organize a line of empty chairs as the list in memory. Each student who sits in a chair represents a value in the list. The first chair in the line of chairs has the index 0. The second chair has the index 1, and so on. Have students follow the code similar to the example below. Substitute in the names of students in your class. For example, chairs[0] = "Pat" means that the student in chair 0 gets up and Pat sits down. If Pat was already in a chair, they would have to get up; in real Python, assignment copies values, but in this simulation, we can’t make copies of students, so we have to simplify by emptying chairs.
# Fill the chairs with students
chairs = ["Alex", "Sam", "Ryan"]
# Students should yell out their names!
print(chairs[1])
print(chairs[0])
print(chairs[2])
# Alex gets up, Pat sits down in chair 0!
chairs[0] = "Pat"   
chairs[1] = "Riley"
chairs[2] = "Alex"
How many chairs did you use in your list? What was the index of the first and last chairs in your class? What would happen if you tried to access a chair that was more than the last index in your list? Write your own code to swap students in chairs and print them out in a different order. Try it out with your classmates!

Activity 3.1.3.

Which code below accesses "Alex" using the following list: chairs = ["Alex", "Sam", "Ryan"]
  • chairs[0]
  • Yes, this would access "Alex". Remember that the first element in an array starts at index 0.
  • chairs[1]
  • No, this would access "Sam". Remember that the first element in an array starts at index 0.
  • chairs[2]
  • No, this would access "Ryan". Remember that the first element in an array starts at index 0.
  • chairs[3]
  • No, this would result in an IndexOutOfBounds error. Remember that the first element in an array starts at index 0.

Activity 3.1.4.

Which code below accesses "Ryan" in the array: chairs = ["Alex", "Sam", "Ryan"]
  • chairs[0]
  • No, this would access "Alex". Remember that the first element in an array starts at index 0.
  • chairs[1]
  • No, this would access "Sam". Remember that the first element in an array starts at index 0.
  • chairs[2]
  • Yes, this would access "Ryan". If there are n elements and you start indexing at 0, the last element is at index n-1.
  • chairs[3]
  • No, this would result in an IndexOutOfBounds error. Remember that the first element in an array starts at index 0.

Subsection 3.1.4 Changing List Elements with Assignment

Click on next in the following Code Lens to see how the list is created in memory and then changed with assignment statements.

Activity 3.1.5.

Click on the Next button at the bottom of the code to see how the values in the list change as you step through the running program. You can see interactive tracing in any Active Code exercise by clicking the Code Lens button.

Activity 3.1.6.

What is printed by the following statements? See the Code Lens above.
numbers = [1,2]
numbers[0] = 2
numbers[1] = numbers[0] + 2
print(numbers)
  • [1, 2]
  • No, the list is changed.
  • [2, 4, 1, 2]
  • No, assignment changes the values. It does not append to the list.
  • [2, 4]
  • Yes, see how each line is calculated in the Code Lens above.
  • [2, 3]
  • No, the 0th element is 2 when the third line is executed.

Activity 3.1.7.

What would the following code print?
values = [3, 2, 1]
values[0] = values[1]
values[2] = values[2] + 1
print(values)
  • [3, 2, 1]
  • That is the original contents of values, but the contents are changed.
  • [2, 0, 2]
  • No, when you set values[0] to values[1] it makes a copy of the value and doesn’t zero it out.
  • [2, 2, 2]
  • Yes, the value at index 0 is set to a copy of the value at index 1 and the value at index 2 is incremented.
  • [2, 3, 1]
  • No, the element at index 2 is the last element in the list since we start counting at 0.
Before making changes to a list, it’s often a good idea to make a copy of it first. Then the original list can be preserved and used later if needed. The [index] notation can be used to access and change elements in a list.
# A list of scores
scores = [95, 87, 92, 100]
# Make a copy of the scores list
scores_bonus = scores
# Add bonus points to the first two scores in the copy
scores_bonus[0] += 5
scores_bonus[1] += 5

Subsection 3.1.5 Length of a List, Random Elements, and Slicing

In Python, you can get the length of a list by using the len(aList) function, note the shortened form of len for length. In AP Pseudocode, the function used is length(aList).
# A list of names
names = ["Jordan", "Alex", "Sam", "Taylor"]
# Get the length of the names list
print("The length of the names list is:", len(names))
Sometimes you may want to pick a random element from the list. One way to do this is to generate a random index. It would start at 0 and go up to the length of the list minus 1. If there are 3 elements in the list, the valid indices would be 0, 1, and 2. In Python, you can use the random.randint() function to generate a random index. The valid indices are 0 through ranodm(0, len(list) - 1. For example, if you have a list of songs, you can select a random song from the playlist using the code below. Python actually has a built-in function called random.choice(list) that will select a random element from a list, but we will use the random index method here to match AP pseudocode.
import random
songs = ["Song 1", "Song 2", "Song 3", "Song 4"]
random_index = random.randint(0, len(songs) - 1)
random_song = songs[random_index]
print(random_song)

Activity 3.1.8.

Use the code below to select a random emoji from the list. Use the random.randint() function to generate a random index and then use that index to access an element in the list. Run the code multiple times to see different emojis printed!
Python also has a cool slicing operator ([start:end]) that allows you to extract a portion of a list from a start index up to (but not including) an end index, just like we saw with strings.

Activity 3.1.9.

Write code that prints out slices of the emoji list, using [start-index : up-to-end-index].

Subsection 3.1.6 Appending to Lists

If you do not know what values you want to store in a list when you create it, you can start with empty list ([]) which is a list that contains no elements and add in elements while the program is running. For example, we can start with an empty shopping list.
# An empty shopping list
shopping_list = []
Elements can be added to a list using the append function which adds the element to the end of the list.
# An empty shopping list
shopping_list = []
shopping_list.append("milk")
shopping_list.append("eggs")
shopping_list.append("bread")
print(shopping_list)
The length of the list will increase as elements are added. Let’s try append and len below.

Activity 3.1.10.

Add two more items to the shopping_list below. Then, print the list and the length of the list.

Subsection 3.1.7 Insert and Remove List Elements

Python also provides built-in functions to change list elements. We already saw the append() function, which adds an element to the end of a list. We can also use list.insert(index, element) that adds an element at a specific index and moves the elements after it one position to the right. It’s important to remember that append, insert, and remove always change the length of the list moving elements to the right or left as needed!
In the AP CSP Pseudocode, the functions to change a list are similar to those in Python, but the AP CSP pseudocode list.remove(index) function removes the element from the list at a certain index. Python has list.remove(value) which deletes the very first occurrence of a specific value from the list or list.pop(index) which removes and returns the element at a specific index, but not a list.remove(index) function.

Activity 3.1.11.

The code below uses a list to keep track of dogs at the animal shelter. Try the insert and remove functions in the code below. Then follow the directions in the comments to insert and remove elements from the list.

Project 3.1.12. Unplugged List of Chairs Revisited.

Let’s revisit the unplugged activity with students in chairs and simulate append, insert, and remove operations. In groups or as a class, organize a line of empty chairs as the list. Have some extra chairs ready to append or insert. Each student who sits in a chair represents an element in the list. The first chair in the line has the index 0. The second chair has the index 1, and so on. Have students follow the code below to insert and remove students and chairs. Substitute in the names of students in your class.
# Fill the chairs with students
chairs = ["Alex", "Sam", "Ryan"]
# Example code to insert and remove students in chairs
chairs.append("Dani") # Add a new chair and student to the end of the list
# Remove the student in chair 1, move students left 1 chair, 
#   and remove the last chair
chairs.remove(1) 
# Insert a new student in chair 1 and move students to the right to make room.
chairs.insert(1, "Taylor")
How do append, insert, and remove affect the list differently than changing the values of existing elements? Write your own code below using append, insert, and remove, and then act it out.

Activity 3.1.13.

What are the values in the list after executing the following AP Pseudocode? Remember that list indexing starts at 0 and the pseudocode uses list.insert(index, value) and list.remove(index) to change the list. Insert and remove always change the length of the list moving elements to the right or left as needed. To trace this code, write down the list after each line of code.
list = [ 0, 3, 5 ]
list.append(7)
list.insert(0, 1)
list.remove(1)
  • [1, 3, 5, 7]
  • Yes, the list is updated as follows: [0, 3, 5], after appends [0, 3, 5, 7], then insert [1, 0, 3, 5, 7], then remove [1, 3, 5, 7].
  • [0, 1, 3, 5, 7]
  • Don’t forget the remove!
  • [0, 3, 5, 7]
  • No, this is correct after the append, but not after the insert.
  • [3, 5, 7]
  • No, the insert does not replace the element but inserts and moves everything down.
What happens if you try to access an element that is not there? Try to access puppies at index 7 below to see what happens. The index must be between 0 and the length of the list - 1 or it will give an error message "IndexError: list index out of range".

Activity 3.1.14.

Run the code below to see an index out of range error. Fix the error by changing the index.

Subsection 3.1.8 Traversing Lists with Loops

Python has a simple way to traverse (step through) a list, visiting each element in the list, using a for loop with the pattern: for item in list:
aList = [1, 2, 3, 4, 5]
for item in aList:
    print(item)

Activity 3.1.15.

Count the number of elements in the list using a for loop and an accumulator variable.
An index-controlled for-loop using range(len(aList)) or a while loop can also be used to traverse a list. The loop variable is the index to access each element in the list. This is why programmers often use the variable i, short for index, as the loop variable. However, it is a lot more complex. If you do not need the index, it is simpler to use the for item in list loop instead. The code below compares all three loops. The first one is the simplest and most often used with lists.
aList = [1, 2, 3, 4, 5]
# Simple for loop for lists
for item in aList:
    print(item)

# More complex indexed for-loop
for i in range(len(aList)):
    print( aList[i] )

# More complex while loop
i = 0
while i < len(aList):
    print( aList[i] )
    i += 1
When we were learning about loops, we learned about the accumulator pattern which uses a loop and an accumulator variable to keep track of the running total as each number is added in. This accumulator pattern is often used to process lists and perform calculations on the elements. In the example above, the count variable is the accumulator variable. In the activity below, we will use sum as an accumulator variable to calculate the sum of all the elements in a list. We can compute the average of a list by dividing the sum by the length of the list using len(list).
scores = [ 100, 90, 95, 85, 93 ]
sum = 0

for number in scores:
    sum += number

Activity 3.1.16.

The following program has the correct code to return the average of a list of numbers, but the code is mixed up. Drag the blocks from the left into the correct order on the right. You will be told if any of the blocks are in the wrong order or are indented incorrectly.

Activity 3.1.17.

Use the accumulator pattern to add taxes to each price in a list of prices. Try Code Lens to see the variable values change as the program runs.

Subsection 3.1.10 Data Abstraction with Lists

In previous lessons, we talked about abstraction in computer science which about focusing on the general features while hiding the specific details. Data Abstraction is the process of hiding the complex implementation details of a data structure and showing only the needed features to the user. Variables are a type of data abstraction because they allow programmers to use a name to represent a value without needing to know how the value is stored in memory. Lists are another type of data abstraction because they allow programmers to use a single variable name to represent a collection of values without needing to know how the values are stored or organized in memory. Data abstraction using lists reduces complexity in code and makes it easier to read, write, and maintain.

Activity 3.1.23.

A programmer creates a program that displays the names of all students enrolled in a class. Which implementation best demonstrates the use of data abstraction?
  • student1 = "Alex"
    student2 = "Marion"
    student3 = "Jordan"
    
  • No. This implementation uses a separate variable for each student rather than treating the related values as a single collection.
  • students = ["Alex", "Marion", "Jordan"]
    
  • Yes. A list allows related values to be treated as a single data abstraction. The programmer can use the name students to work with the collection without needing separate variables for each student.
  • studentCount = 3
    
  • No. This variable stores the number of students but does not provide a collection containing the students’ names.
  • print("Alex")
    print("Marion")
    print("Jordan")
    
  • No. This implementation contains repeated statements instead of using a single abstraction to represent the related student names.
Refactoring code means to rewrite the code to improve it while maintaining the same functionality. Adding data abstraction is a great way to refactor code to reduce its complexity and make it more maintainable and easier to understand. Try it below!

Activity 3.1.24.

Refactor the following code to use a list instead of individual variables. Make sure you use a for-loop to traverse the list and print each favorite food.
Data abstraction also makes it easier to add data without having to rewrite the algorithms. Try adding data to the list below. You will see that you do not need to rewrite the loop processing the list at all. This makes it much easier to maintain and update the code.

Activity 3.1.25.

Add at least 3 more colors to the list below. Do you need to change the for-loop?
Data abstraction using lists also removes a lot of repetitive duplication in code. Instead of having multiple variables and repeated code to process each variable, we can use a single list and a loop to process all the elements.

Activity 3.1.26.

Consider the following code.
temperatures = [72, 75, 68, 70]
total = 0
for temperature in temperatures:
    total = total + temperature
print(total)
Which of the following are reasons why using data abstraction with a list reduces program complexity? Select two answers.
  • The same algorithm can process the data even if we add new temperatures or update or remove temperatures.
  • Yes. The loop processes each element in the list, so the same algorithm can work with different amounts of data without needing to be rewritten.
  • The list reduces the need for repeated variables and statements for processing individual temperatures.
  • Yes. Without a list, the programmer might need separate variables and repeated statements for each temperature. Using a list and loop reduces this repeated code.
  • The list automatically calculates the sum of the temperatures.
  • No. The list only stores the temperatures. The for loop and addition operation are responsible for calculating the sum.
  • The list guarantees that there are no duplicate temperatures.
  • No. A list can contain duplicate values. Preventing duplicate values is not a reason why using a list reduces program complexity.

Subsection 3.1.11 Coding Challenge: Lists

A bakery uses parallel lists to store the names, emoji images, and prices of baked goods in three lists. The lists are kept in parallelorder so that an index can be used to access the corresponding elements in each list. For example, the first element in the list of baked goods corresponds to the first element in the list of prices, the second element corresponds to the second element, and so on. This allows a program to easily look up the price and image of a baked good by index. In the following coding challenge, you will use an input-controlled while loop to ask the user to choose baked goods from the bakery and put its index in an order list. You will then print out their receipt and calculate the total cost of their order using a for loop and the order list.

Project 3.1.27. Bakery Parallel Lists.

A bakery uses 3 parallel lists below to store the names, emoji images, and prices of baked goods. The while-loop below prints the lists and asks for the user’s order by choosing an index number. You will write code to append the chosen index to the order list after checking that it is in range. You will then print out their receipt and calculate the total cost of their order using a for loop and the order list.

Activity 3.1.28. Data Abstraction Reflection.

Consider the lists used in your project code above.
  1. Explain how the lists use data abstraction to manage complexity in your program.
  2. Explain how your code would be more complex if you did not have lists.
  3. If the bakery decides to add more baked goods to the menu, describe how you would need to adjust your code. How do lists make this easier?

Subsection 3.1.12 Vocabulary Review

Activity 3.1.29.

You have attempted of activities on this page.