Loops and functions
Doing something once per row, and naming a piece of work so you never write it twice.
You now have containers. These are the two ways you do something with what is in them.
A loop does something once per item
for city in cities:
print(city)
city is a name you chose; Python assigns each item to it in turn. The indented
block runs once per item.
Over a list of dictionaries — the table shape from the last lesson — this is the whole of "process every row":
for student in students:
print(student["name"], student["marks"])
Building a new list as you go
This pattern appears constantly:
passed = []
for student in students:
if student["marks"] >= 80:
passed.append(student["name"])
Start empty, loop, keep the ones you want. Python has a shorter way to write it:
passed = [s["name"] for s in students if s["marks"] >= 80]
That is a comprehension. It does exactly the same thing. Write the long version until the short one reads naturally to you — there are no points for brevity you cannot read at speed six months later.
A function names a piece of work
def grade(marks):
if marks >= 80:
return "A"
if marks >= 60:
return "B"
return "C"
grade(88) # "A"
def defines it, the value in brackets is what goes in, return is what comes
out. Nothing happens until you call it.
Why bother, when the loop already worked
Because the rule will change.
The day someone decides the A threshold is 85, you edit one function. If you had
written that if chain inline in four different places — and you will, because
grading turns up in the report, the chart, the export and the check — you now have
to find all four, and you will find three.
A function is the difference between one edit and a search. That is the entire argument, and it is enough.
Try this
Write a function that takes a list of students and returns the average marks. Then
use it. If you get stuck on the average, that is the point — write the loop first,
make it work, and only then wrap it in def.