A. Programming Concepts and Skills · Arrays and SubprogramsDeclaring, Initializing, Accessing and Modifying Lists
A1.6 A1.5 A4.1About 70 minutes
Learning goals- I can declare and initialize a list in several ways, including from user input.
- I can access and change an element by its index.
- I can add and remove elements with append, insert, pop, remove and del, and predict how the other elements shift.
- I can explain the difference between two names for one list (an alias) and a true copy.
Words to know
declare
To introduce a variable (here, an array) to the program. In Python, a list is declared the first time you assign it, e.g. marks = [].
initialize
To give an array its starting values, e.g. counts = [0] * 6.
method
A subprogram that belongs to a value and is called with a dot, e.g. marks.append(87).
append
To add an element to the end of a list: a.append(x).
mutable
Able to be changed after it is created. Lists are mutable; strings and numbers are not.
alias
A second name for the same list. Changing the list through one name is visible through the other.
ValueError
The run-time error Python raises when a value is the right type but not acceptable, e.g. removing an element that is not in the list.
A sign-up sheet that changes
Your school is running a Winter Carnival snowshoe race. Students sign up all week. Some add their names, a few drop out, and the organizer fixes a misspelled name. A list that only sits there is not much use: real programs create lists, read them, and change them. The curriculum calls this declaring, initializing, modifying and accessing an array. This lesson shows you each one in Python.
Declaring and initializing
In languages like Java you declare an array with its type and size before you use it, e.g. int[] counts = new int[6];. Python is simpler: a list is declared the moment you assign it. The starting values you give it are its initialization. Here are four common ways:
names = [] # empty list, to be filled later
marks = [78, 91, 66, 85] # literal values
counts = [0] * 6 # six zeros
years = list(range(2020, 2025)) # 2020 to 2024
print(names, marks, counts, years)
Output: [] [78, 91, 66, 85] [0, 0, 0, 0, 0, 0] [2020, 2021, 2022, 2023, 2024]. [0] * 6 repeats the list [0] six times. Use it when you know the size but not the values yet.
Accessing and modifying one element
You already know that marks[1] reads the element at index 1. Put the same thing on the left of = and you change that element. This is allowed because lists are mutable.
marks = [78, 91, 66, 85]
marks[2] = 70 # replace 66 with 70
marks[0] = marks[0] + 5 # add 5 to the first mark
print(marks)
Output: [83, 91, 70, 85]. The length does not change; two elements were replaced.
You can only change elements that already exist. marks[4] = 60 on a list of length 4 raises IndexError: list assignment index out of range. To make a list longer, use the methods below.
Adding and removing elements
A method is a subprogram that belongs to a value. You call it with a dot: list_name.method(...).
a.append(x) adds x to the end.a.insert(i, x) puts x at index i; everything from i onward shifts one place right.a.pop() removes the last element and gives it back (returns it). a.pop(i) removes and returns the element at index i; everything after it shifts left.a.remove(x) removes the first element equal to x. If x is not there: ValueError.del a[i] deletes the element at index i (nothing is returned).x in a is True if x is an element of a. Use it before remove to avoid the ValueError.
insert(2, "Cy") puts "Cy" at index 2 and shifts "Dev" and "Eli" (blue) one place to the right. Then pop(0) removes "Ava" and every other element shifts one place left, so all the indexes change.Worked exampleExample 1: Trace the sign-up list
Predict what this prints, keeping track of the list after every line.
sign_up = ["Ava", "Ben", "Dev"]
sign_up.append("Eli")
sign_up.insert(2, "Cy")
first = sign_up.pop(0)
sign_up.remove("Dev")
sign_up[0] = "Bea"
print(first, sign_up, len(sign_up))
- Line 1:
["Ava", "Ben", "Dev"] - Line 2, append:
["Ava", "Ben", "Dev", "Eli"] - Line 3, insert at index 2:
["Ava", "Ben", "Cy", "Dev", "Eli"] - Line 4, pop(0) removes and returns "Ava", so
first is "Ava": ["Ben", "Cy", "Dev", "Eli"] - Line 5, remove("Dev"):
["Ben", "Cy", "Eli"] - Line 6, replace index 0:
["Bea", "Cy", "Eli"]. The length is 3.
Ava ['Bea', 'Cy', 'Eli'] 3
Filling a list from user input
Most lists are built while the program runs. The pattern is: start with an empty list, loop, and append each new value. Remember from Programming Basics that input() always returns a string, so convert it with int() or float() first.
snowfall = []
for day in range(1, 4):
cm = float(input("Snowfall on day " + str(day) + " (cm): "))
snowfall.append(cm)
print("You entered:", snowfall)
A sample run where the user types 4.5, 0 and 12: the program shows three prompts and then You entered: [4.5, 0.0, 12.0].
Another common way is to read all the values on one line and split them. input().split() breaks the line at the spaces and gives a list of strings. A loop then converts each one:
words = input("Enter marks separated by spaces: ").split()
marks = []
for w in words:
marks.append(int(w))
print(words)
print(marks)
If the user types 78 91 66, the program prints ['78', '91', '66'] (strings, in quotes) and then [78, 91, 66] (integers).
Two names for one list: aliasing
Here is a surprise that catches many programmers. When you write b = a for a list, Python does not copy the list. It makes b a second name, an alias, for the same list. Change the list through b and you will see the change through a too. To get an independent copy, use a.copy() (or list(a), or the slice a[:]).
Left: b = a makes two names point to one list, so b[0] = 0 would also change a[0]. Right: a.copy() builds a second list with the same values, so changing c leaves a alone.a = [5, 9, 2]
b = a
c = a.copy()
b[0] = 0
c[1] = 100
print(a)
print(b)
print(c)
Output: [0, 9, 2], [0, 9, 2], [5, 100, 2]. Changing b also changed a (same list). Changing c did not (separate copy).
Worked exampleExample 2: Fix the run-time errors
Each line below crashes. Name the error and fix it.
(a) teams = ["Leafs", "Jets"] then teams[2] = "Oilers"
(b) teams = ["Leafs", "Jets"] then teams.remove("Canucks")
(c) scores = [] then print(scores.pop())
- (a) IndexError: list assignment index out of range. Index 2 does not exist yet; you can only assign to existing indexes. Fix:
teams.append("Oilers"). - (b) ValueError: list.remove(x): x not in list. Fix: check first,
if "Canucks" in teams: teams.remove("Canucks"). - (c) IndexError: pop from empty list. There is nothing to remove. Fix: check first,
if len(scores) > 0: print(scores.pop()).
Use append to grow a list, and check with in or len() before removing.
Just for funA list walks into a café and asks for a coffee. The barista says, "Sorry, we're all out."
The list says, "No problem, I'll just .pop() next door."
Hands-on activityShuffle the line-up
You need: 6 to 8 index cards or paper slips, a pen, and a computer with Python.
- Write a different name of a Canadian city on each card and lay 5 of them in a row on a table. Put a small index-number card under each position (0, 1, 2, ...).
- Ask a family member to read out instructions from this list one at a time, while you move the cards:
append("Iqaluit"), insert(1, "Halifax"), pop(0), remove("Regina") (if you have it), pop(). After each move, update the index cards so they still start at 0. - Write your predicted final list on paper. Then type the same starting list and instructions into Python and print the list after each step. Did your table match Python every time?
What to look for: when a card is inserted or removed in the middle, the student notices that the index of every card after it changes.
Your turn
1Write one line that creates a list called zeros holding ten 0s.
2marks = [70, 82, 95]. Write a line that changes 82 to 85.
3Predict the output:
a = [1, 2, 3]
a.append(4)
a.insert(0, 9)
print(a)
4Predict the output:
a = [10, 20, 30, 40]
x = a.pop(1)
print(x, a)
20 [10, 30, 40]. pop(1) removes the element at index 1 and returns it.
5What is the difference between a.pop(2) and a.remove(2)?
pop(2) removes the element at index 2. remove(2) removes the first element whose value is 2.
6Why does marks[3] = 77 crash when marks = [70, 82, 95]? How do you add 77 at the end?
The upper bound is 2, so index 3 does not exist (IndexError). Use marks.append(77).
7Predict the output:
x = [1, 2]
y = x
y.append(3)
print(len(x))
3. y is an alias for the same list, so appending through y also changes x.
More practice: warm-up
1Which method adds an element to the end of a list?
3What does list(range(4)) make?
4What type of value does input() give back?
A string, even when the user types digits.
5What does 3 in [1, 2, 3] give?
More practice: on your own
1Predict the output:
t = [-5, -9, 2]
t[1] = t[0] + t[2]
t.append(t[1] * 2)
print(t)
[-5, -3, 2, -6]. t[1] becomes −5 + 2 = −3; then −3 × 2 = −6 is appended.
2Predict the output:
a = ["a", "b", "c", "d"]
del a[1]
a.insert(1, "z")
print(a)
['a', 'z', 'c', 'd']. Deleting index 1 removes "b"; inserting "z" at index 1 puts a new element in the same spot.
3Write a program that asks how many maple trees a student measured, then reads that many heights in metres (one per line) into a list and prints the list.
n = int(input("How many trees? "))
heights = []
for i in range(n):
heights.append(float(input("Height (m): ")))
print(heights)
With inputs 2, 14.5, 9 it prints [14.5, 9.0].
4Predict the output:
a = [3, 1, 3, 1]
a.remove(1)
print(a)
[3, 3, 1]. remove deletes only the first 1 it finds.
5Give three different ways to make an independent copy b of a list a.
b = a.copy(), b = list(a), b = a[:].
Challenge
1Predict the output and explain:
a = [1, 2, 3]
b = a
b = b + [4]
print(a, b)
[1, 2, 3] [1, 2, 3, 4]. b + [4] builds a new list, and b = ... makes b name that new list. a still names the old one. (By contrast, b.append(4) would change the shared list.)
2A list q holds a line of customers at a skating rink rental desk. Write code that serves (removes and prints) the first customer, then adds "Noor" at the end. Why is pop(0) slower than pop() on a very long list?
print(q.pop(0)) then q.append("Noor"). pop(0) must shift every remaining element one place left, so the work grows with the length; pop() removes the last element with nothing to shift.
3Predict the output:
a = [0] * 3
for i in range(3):
a[i] = i * i
a.insert(1, a[-1])
print(a)
[0, 4, 1, 4]. After the loop a is [0, 1, 4]. a[−1] is 4, inserted at index 1.
Check your understandingQuiz
1. Which line creates a list of five zeros?
2. a = [4, 8, 12]. After a.insert(0, 2), what is a[1]?
4. a = [1, 2, 3]. Which line raises a run-time error?
5. After x = [1, 2] and y = x and y[0] = 9, what is x?
6. A user types 5 10 15. What is input().split()?
For parents and teachersBig idea: Expectation A1.6 asks students to write programs that declare, initialize, modify and access one-dimensional arrays. This lesson covers each of those in Python, plus the run-time errors (A4.1) that come from misusing them.
How to help: The card activity is worth doing for real; moving physical cards makes "everything shifts" obvious. Afterwards, call out a short sequence of list operations and ask your teen to predict the result before running it.
Common difficulties:
- Confusing
pop(i) (by index) with remove(x) (by value). - Trying to grow a list with
a[len(a)] = x. Python requires append or insert. - Forgetting that
input() gives strings, so ["78", "91"] is not a list of numbers. - Aliasing. If two variables seem to change together, check for a
b = a line. Use .copy() when an independent list is wanted.