LambdaLabTM
Computer Science · Class 11 · Lists Revisited
ListsTraversal⏱️ 13 min read

Two Ways to Walk a List

The same two loops as the strings chapter, over a list this time — and one new fact that changes everything. A string cannot be altered, so there the choice was only about knowing where you were. A list can be altered, and only one of the two loops is able to do it.

1The two loops, and their identical output

A list is a sequence, so a for loop hands out its items in order — exactly as it does with a string, only the items are whole values rather than single characters:

by_item.py
# the loop hands out one item at a time

marks = [56, 91, 43, 78]

for m in marks:
    print(m)
Output
56
91
43
78
by_index.py
# the loop hands out one position at a time

marks = [56, 91, 43, 78]

for i in range(len(marks)):
    print(marks[i])
Output
56
91
43
78

Identical output again, and the same real difference underneath: m holds the item — the number 56 — while i holds a position — the number 0 — and the item has to be fetched with marks[i].

Key Takeaway
The first question is still the same one. Do you need to know where you are? Printing a numbered list needs the position; adding marks up does not. What is new is a second question, and on lists it matters more.
numbered.py
# with the position, the item can be numbered

marks = [56, 91, 43, 78]

for i in range(len(marks)):
    print('Student', i + 1, 'scored', marks[i])
Output
Student 1 scored 56
Student 2 scored 91
Student 3 scored 43
Student 4 scored 78

2The new question: can it change the list?

Here is a program that looks completely reasonable and does absolutely nothing. It is meant to give every student five grace marks:

grace_broken.py
# trying to raise every mark by 5, with the item form

marks = [10, 20, 30]

for m in marks:
    m = m + 5

print(marks)
Output
[10, 20, 30]

And here is the same job, written with positions:

grace.py
# the same job, with the index form

marks = [10, 20, 30]

for i in range(len(marks)):
    marks[i] = marks[i] + 5

print(marks)
Output
[15, 25, 35]
Key Takeaway
m is a box of its own; marks[i] is a place in the list. The loop hands m a copy of each item, so m = m + 5 moves that box and the list is never told anything. marks[i] = … writes through the position, into the list itself. This is the same lesson as ch on a string — except that there, no loop could have changed the string, because a string cannot be changed at all.

3Watch the list, three ways

Three programs, the same list, one round at a time. Watch the boxes underneath each one: on the left they never move, however many rounds go by.

📋 Give every mark 5 grace marks

Three programs, the same list, one round at a time. One of them does nothing at all.

By itemm holds a copy of the item
for m in marks:
m = m + 5
m
marks
56
0
91
1
43
2
78
3
By indexi holds a position
for i in range(len(marks)):
marks[i] = marks[i] + 5
i
marks
56
0
91
1
43
2
78
3
Build a new lista second list is built
raised = []
for m in marks:
raised.append(m + 5)
m
marks
56
0
91
1
43
2
78
3
raised
[] — empty

Nothing has run yet. Watch the list below as the loop goes round.

Nothing has run yet. Watch the list below as the loop goes round.

Nothing has run yet. raised is an empty list, waiting to be filled.

Tip
The third column is a real answer, not a consolation prize. Building a new list with append() leaves the original untouched, which is what you want when the old values still matter — and it is the only way to do it when the new list is a different length from the old one, as it is when you keep only the evens.

4What actually differs

 by itemby index
the headerfor m in marks:for i in range(len(marks)):
the loop variable holdsan item, 56a position, 0
to use the itemmmarks[i]
knows its position?noyes
can change the list?noyes — marks[i] = …
can see the neighbours?noyes — marks[i + 1]
grace.py

5Recap

for m in marks gives you the item

Shorter and enough for anything that only reads: totals, counts, tests, and building a second list.

for i in range(len(marks)) gives you a position

The item costs one lookup, marks[i] — and in exchange you know where you are and can write back.

m = m + 5 changes nothing

The loop variable is a copy in a box of its own. Everybody writes this program once; the list comes out exactly as it went in.

Two questions, not one

Do I need the position? And do I need to change the list? A yes to either one means the index form.

Quick Check

marks = [10, 20, 30]; for m in marks: m = m + 5. What does print(marks) show?

Quick Check

Which loop can print 'Student 3 scored 43'?

Quick Check

Which is the better way to build a list of only the even numbers from another list?