Traversal by Item
for m in marks: — the form to reach for whenever the program only reads the list. It cannot change one, and most programs do not need to: they add the items up, count the ones that pass a test, look for the biggest, or build a second list beside the first.
1The four collectors, and that is most of it
total = 0Adds each item. Zero is the value that changes nothing.
count = 0Goes up by 1 when the item passes a test — by 1, not by the item.
best = marks[0]The best seen so far. Starts as a real member of the list.
result = []Grows by append(). The original is never touched.
2Program 1 — the total and the average
Add up a list of marks and print the class average — without sum().
# the total and the average, without sum()
marks = [72, 65, 88, 91, 54]
total = 0
for m in marks:
total = total + m
print('Total:', total)
print('Average:', total / len(marks))Total: 370 Average: 74.0
total = 0Above the loop, so it is made once and survives every round. Inside the loop it would be wiped each time and the answer would be the last mark.
total = total + mThe right-hand side is worked out first — the old total plus this round's mark — and the answer goes back into the same box.
print('Average:', total / len(marks))After the loop, and divided by len(marks) rather than by 5, so adding a sixth mark to the list needs no other change.
sum(marks) and len(marks). sum(marks) / len(marks) is the whole program in one line, and it is what you would write in real code. The loop is what the question is testing — and it is the one that keeps working the moment the rule gets fussier, as it does in program 5.3Program 2 — how many even, how many odd?
Count the even and the odd numbers in a list.
# how many even numbers, and how many odd?
numbers = [12, 7, 30, 45, 8, 21, 64]
evens = 0
odds = 0
for n in numbers:
if n % 2 == 0:
evens = evens + 1
else:
odds = odds + 1
print('Even numbers:', evens)
print('Odd numbers:', odds)Even numbers: 4 Odd numbers: 3
Two counters, one if…else, and the check that the program is right: 4 + 3 = 7, which is len(numbers). Every item landed in exactly one of the two, which is what an else guarantees and two separate ifs would not.
evens = evens + 1, not evens = evens + n. A counter goes up by one per item; a total goes up by the item. Mixing them up is the commonest slip on this page, and the answer it produces — 114 “even numbers” — is obviously wrong only if you look.4Program 3 — the largest and the smallest
Find the highest and lowest mark in a list, without max() or min().
# the largest and the smallest, without max() and min()
marks = [56, 91, 43, 78, 65]
largest = marks[0]
smallest = marks[0]
for m in marks:
if m > largest:
largest = m
if m < smallest:
smallest = m
print('Largest:', largest)
print('Smallest:', smallest)Largest: 91 Smallest: 43
marks[0]. Not at 0, and not at 100. A champion has to start as a real member of the list, or it can win: start largest at 0 and a list of negative temperatures reports a highest of 0, which is not in the list at all. Starting at marks[0] can never be wrong, because that value really is one of the candidates.Two separate ifs, not if…elif: both questions must be asked of every mark. With an elif, a mark that beat the largest would never be tested against the smallest — harmless here, and exactly the kind of thing that is not harmless later.
5Program 4 — a new list of squares
Build a second list holding the square of every number in the first, and show that the original is untouched.
# a new list holding the square of every number
numbers = [2, 5, 7, 10]
squares = []
for n in numbers:
squares.append(n * n)
print('Original:', numbers)
print('Squares: ', squares)Original: [2, 5, 7, 10] Squares: [4, 25, 49, 100]
squares = []An empty list, made before the loop. It is the same collector idea as total = 0 — the value that means 'nothing yet' for a list is [].
squares.append(n * n)append() adds one item to the end. It changes squares and hands back nothing, which is why it is never written as squares = squares.append(...) — that would put None where the list was.
squares = squares.append(n * n) destroys the list. append() is one of the methods that changes the list rather than answering with a new one, so it returns None — and assigning that back puts None in squares. The very next round then fails with AttributeError: 'NoneType' object has no attribute 'append'.6Program 5 — how many are above the average?
Work out the class average, then count how many marks beat it.
# how many marks are above the class average?
marks = [72, 65, 88, 91, 54]
total = 0
for m in marks:
total = total + m
average = total / len(marks)
count = 0
for m in marks:
if m > average:
count = count + 1
print('Average:', average)
print('Above average:', count)Average: 74.0 Above average: 2
This is also where sum() stops rescuing you. The first loop could be total = sum(marks), but the second one has no built-in at all — there is no function for “count the items above this number”.
7Recap
0 for a total, 0 for a count, marks[0] for a champion, [] for a new list. All four are made before the loop starts.
A total goes up by the item. They look alike and they answer different questions.
marks[0] is always safe. A made-up starting value like 0 or 100 can win, and then the answer is not in the list.
Write squares.append(x) on its own line. Never squares = squares.append(x) — that stores None and the next round crashes.
- 1
Count how many marks in a list are 33 or above.
Hint · One counter, one
if. The counter goes up by 1, not by the mark. - 2
Add up only the numbers that divide by 3.
Hint · A total this time, so it goes up by
n— and the test isn % 3 == 0. - 3
Build a new list holding only the positive numbers.
Hint · An empty list above the loop,
append()inside theif. The new list will be shorter than the old one. - 4
Find the longest name in a list of names, without
max().Hint · The champion program with
len(name) > len(longest), starting atnames[0]. - 5
Count how many numbers are below the average and how many are exactly equal to it.
Hint · The two-pass shape, with an
if…elif…elsein the second loop.
Why must largest start at marks[0] rather than at 0?
What is wrong with squares = squares.append(n * n)?
Why does the above-average program need two loops?