Functions gave the repeated chunk a name. The next hour produced three complaints, all of them fair: the function needed two pieces of information, not one; somebody wanted the answer stored rather than printed; and a variable that clearly existed inside the function was β€œnot defined” the moment anyone tried to use it outside. Those three complaints are this page.

Handing information in

def practice_summary(name, minutes, target=150):
    if minutes >= target:
        return f"{name}: {minutes} min β€” target met."
    short = target - minutes
    return f"{name}: {minutes} min β€” {short} short of target."

name, minutes, and target are parameters β€” names that exist inside the function, filled in when somebody calls it. The values supplied at the call are the arguments:

print(practice_summary("Priya", 185))
print(practice_summary("Sam", 90))
print(practice_summary("Sam", 90, 60))
Priya: 185 min β€” target met.
Sam: 90 min β€” 60 short of target.
Sam: 90 min β€” target met.

Position decides which is which, so the order in the call must match the order in the definition. target=150 is a default: leave the third argument out and the function supplies 150 itself, which is how the same function serves a coach with one target and a club with another. Leave out something with no default and Python says so precisely:

TypeError: practice_summary() missing 1 required positional argument: 'minutes'

Handing an answer back

return does two things at once: it hands a value to whoever called the function, and it ends the function immediately. Both lines above are return statements, and only one of them ever runs β€” the second return is unreachable when the target is met.

That is the pattern called an early return, and it is usually kinder to the reader than nesting the rest of the function inside an else. A function stops at the first return it reaches, so put the simple case first and let the rest of the body assume it is past.

Where a variable lives

def total_minutes(sessions):
    total = 0
    for value in sessions:
        total = total + value
    return total
 
total_minutes([45, 60])
print(total)
NameError: name 'total' is not defined

total is local: it is created when the function starts and gone when it ends. That looks like an obstacle for about a day, and then it turns into the reason functions are trustworthy. A local variable cannot be quietly changed by another part of the program, and two functions can both use a variable called total without ever colliding. Anything the caller needs, the function returns.1

Functions built from functions

Once a function returns a value, other functions can use it β€” and that is where a program starts to feel designed rather than typed:

def as_hours_and_minutes(minutes):
    hours = minutes // 60
    rest = minutes % 60
    return f"{hours} h {rest} min"
 
def report(name, minutes):
    return f"{name} practised {as_hours_and_minutes(minutes)}."
 
print(report("Priya", 185))
Priya practised 3 h 5 min.

as_hours_and_minutes knows nothing about coaches, players, or reports. That ignorance is the point: it is a piece you can lift into the next program unchanged, which is what modularity actually buys you.

You are also standing on functions somebody else wrote β€” len, abs, round, max, and, with an import random at the top, random.randint(1, 6). Before writing a helper, check whether Python already has it; reading documentation to find out is a real skill, and Getting Unstuck is where it gets practised.

Build the habit in Functions Practice, read a complete program made of three small functions in Writing Functions, then use them to carve up something bigger in Decomposition and Design.

Curriculum connection

A3.1

demonstrate the ability to use existing subprograms (e.g., random number generator, substring, absolute value) within computer programs;

Link to original

A3.2

write subprograms (e.g., functions, procedures) that use parameter passing and appropriate variable scope (e.g., local, global), to perform tasks within programs.

Link to original

B2.3

apply the principle of modularity to design reusable code (e.g., subprograms, classes) in computer programs;

Link to original

Footnotes

  1. Python does have a global keyword that lets a function reach out and change a variable defined outside it. It is legal, it is occasionally the right answer, and in this course it is almost never the right answer β€” a function that changes things nobody can see from the call is exactly the kind of code that is impossible to hand to somebody else. ↩