Learning Goals
3 minBy the end of this lesson you can:
- Write small returning functions for
square,cube,averageandis_evenfrom a blank file. - Use boolean-returning functions like
is_even(n)directly inside anifcondition. - Compose function calls — pass the return of one into another — to answer real questions in one expression.
Warm-Up
5 minWithout typing, predict what each line prints:
def square(n): return n * n print(square(5)) print(square(square(2))) print(square(3) + square(4))
Show the answers
25 16 25
square(5) is 25. square(square(2)) evaluates the inside first — square(2) is 4, then square(4) is 16. square(3) + square(4) is 9 + 16 = 25, the legendary Pythagorean triangle 3-4-5. Three different shapes of call, all just because square returns a value.
Think of each function as a tool in a tray. Today we make four small tools. The interesting work is in combining them.
Reminder · The Four-Line Function Pattern
10 minEvery function we write today fits this shape
def name(parameters): # do the maths return answer
Three lines if it's really small. No print inside — the function's job is to compute and return. The main program decides what to do with the answer.
Boolean returns · the is_X pattern
Functions whose name starts with is_ almost always return True or False. They're built to drop straight into an if:
def is_even(n): return n % 2 == 0 if is_even(10): print("even") else: print("odd")
Read the if line out loud — "if is even ten". Almost English. That's why this naming convention exists.
Why n % 2 == 0 works
From PY-L1-04: % gives the remainder after division. Even numbers divided by 2 have remainder 0, odd numbers have remainder 1. So n % 2 == 0 is a boolean expression that's already True or False — and we can return it directly. No need to write:
# verbose — don't do this def is_even(n): if n % 2 == 0: return True else: return False # concise — do this def is_even(n): return n % 2 == 0
The expression is the boolean. You don't wrap it in an if.
Composing functions · cube as squared-times-itself
Sometimes one function can use another. cube(n) is just square(n) * n:
def square(n): return n * n def cube(n): return square(n) * n # reuses square — no duplicated maths print(cube(4)) # → 64
If we ever rewrote square (maybe to handle weird inputs), cube would automatically benefit. That's the "build with what you've built" payoff.
Worked Example · Build the Toolbox
14 minStep 1 · Four small tools, one file
Save as math_toolbox.py:
# math_toolbox.py — four tools def square(n): return n * n def cube(n): return n * n * n def average(a, b): return (a + b) / 2 def is_even(n): return n % 2 == 0
Four functions, twelve lines including blank lines. None of them prints anything — they all compute and return.
Step 2 · Try each one once
print(square(6)) # 36 print(cube(4)) # 64 print(average(10, 30)) # 20.0 print(is_even(7)) # False
Step 3 · Combine them
Real questions usually need more than one tool. Here are three little puzzles, each solved by combining functions:
# Q1: what's the average of 3 squared and 4 squared? print(average(square(3), square(4))) # average(9, 16) = 12.5 # Q2: is the cube of 5 even? print(is_even(cube(5))) # cube(5) = 125 → False # Q3: what's the average of two numbers, but only if both are even? a = 10 b = 20 if is_even(a) and is_even(b): print("Even pair, avg =", average(a, b)) else: print("At least one is odd.")
Notice how each tool slots into the other. The function names tell the story; the bodies are tiny and out of the way.
Step 4 · A mini report driven by the toolbox
Code
# math_toolbox.py — full version with a tiny report def square(n): return n * n def cube(n): return n * n * n def average(a, b): return (a + b) / 2 def is_even(n): return n % 2 == 0 # main program — explore numbers 1..6 print("n | square | cube | even?") print("-" * 30) for n in range(1, 7): print(" ", n, " ", square(n), " ", cube(n), " ", is_even(n)) print() print("Average of squares 1..6 first and last:", average(square(1), square(6)))
Sample run
n | square | cube | even? ------------------------------ 1 1 1 False 2 4 8 True 3 9 27 False 4 16 64 True 5 25 125 False 6 36 216 True Average of squares 1..6 first and last: 18.5
Small returning functions at the top, a short main program at the bottom that calls them. Once you internalise this shape, big programs stop feeling intimidating — they're just stacks of these little tools.
Try It Yourself
13 minThree tasks. Every function must return — no print inside the function body.
Write triple(n) that returns n * 3. Print the triples of 4, 11 and 100.
Hint
def triple(n): return n * 3 print(triple(4)) # 12 print(triple(11)) # 33 print(triple(100)) # 300
Three lines of body for the whole program. If you put a print inside the function, the values would appear but you couldn't use them in triple(triple(2)) kinds of tricks.
is_positiveWrite is_positive(n) that returns True if n > 0, else False. Use it in an if to test the numbers 5, 0 and -3. Print <n>: positive or <n>: not positive.
Hint
def is_positive(n): return n > 0 for n in [5, 0, -3]: if is_positive(n): print(n, ": positive") else: print(n, ": not positive")
The function body is one line — return n > 0 — because n > 0 already evaluates to a boolean. No need for an extra if inside the function.
Write average3(a, b, c) that returns the average of three numbers. Then write a tiny program that asks the user for three test scores with input(), converts each to float (callback from PY-L1-07), and prints their average rounded to 1 decimal place using the built-in round().
Hint
def average3(a, b, c): return (a + b + c) / 3 s1 = float(input("Score 1: ")) s2 = float(input("Score 2: ")) s3 = float(input("Score 3: ")) avg = average3(s1, s2, s3) print("Average:", round(avg, 1))
The function only does the maths. The main program handles input, conversion, and display. That separation is the lesson's real lesson.
Mini-Challenge · Wei's Stuck Toolbox
8 minWei wrote four functions but only two work. Find and fix the three bugs.
# wei_toolbox.py — buggy
def square(n):
print(n * n)
def cube(n):
return n * n * n
def average(a, b)
return (a + b) / 2
def is_even(n):
if n % 2 == 0:
return "yes"
else:
return "no"
print(square(4) + 10) # crashes
print(cube(3)) # works → 27
print(average(2, 8)) # crashes
if is_even(6):
print("even") # prints "even"... but try is_even(5) too- Bug 1.
squareusesprintinstead ofreturn.square(4) + 10tries to addNone + 10and crashes. - Bug 2.
averageis missing the colon at the end of thedefline. - Bug 3.
is_evenreturns strings ("yes"/"no") instead of booleans. Theifstill works because both non-empty strings are truthy — meaningis_even(5)would also print "even". Quietly broken.
Show one possible fix
# wei_toolbox.py — fixed def square(n): return n * n def cube(n): return n * n * n def average(a, b): return (a + b) / 2 def is_even(n): return n % 2 == 0 print(square(4) + 10) # 26 print(cube(3)) # 27 print(average(2, 8)) # 5.0 if is_even(6): print("even") # prints "even" if is_even(5): print("this should NOT print")
Bug 3 is the subtle one. Returning "yes"/"no" looks fine — and the function works as a label printer. But the moment you drop it into if is_even(n), every call returns a non-empty string, which is always truthy. The function name promises a boolean; deliver one.
Recap
3 minToday wasn't about learning new keywords — it was about feeling how the keywords fit together. Four tiny returning functions, then a main program that chains them, slots them into if conditions, and composes them inside one expression. That stack — small tools at the top, a readable script at the bottom — is the shape every real Python program takes. Boolean-returning functions named is_X are especially nice because they drop straight into conditions and make your code read like English. Next lesson we'll mix functions with lists from PY-L1-15..L1-18.
Vocabulary Card
- boolean-returning function
- A function that returns
TrueorFalse. By convention, named with anis_orhas_prefix. - composing functions
- Passing one function's return value into another, like
average(square(3), square(4)). - helper function
- A small returning function used inside a bigger one — like
cubecallingsquare. - truthy / falsy
- Values that act like
True(any non-empty string, any non-zero number) or likeFalse(empty string"",0,None) when used in anif. - one job per function
- The guideline that each function should either compute (and return) or display (and print) — not both at once.
Homework
4 minCreate a new file my_toolbox.py. Build six small functions and use them in a short main program.
square(n)→ returnsn * ncube(n)→ returnsn * n * n(orsquare(n) * nif you want to reusesquare)average(a, b)→ returns(a + b) / 2is_even(n)→ returnsn % 2 == 0is_positive(n)→ returnsn > 0biggest(a, b)→ returns the larger of two numbers (useif/else; don't use the built-inmax()this time)- In the main program, ask the user for two numbers with
input()(cast toint). Use every function at least once to print a short report — e.g. their squares, their cubes, their average, whether each is even, whether each is positive, and which one is bigger.
Bring my_toolbox.py next class. In PY-L1-31 we'll start passing entire lists into functions.
Sample · my_toolbox.py
# my_toolbox.py — six small tools + one report def square(n): return n * n def cube(n): return square(n) * n def average(a, b): return (a + b) / 2 def is_even(n): return n % 2 == 0 def is_positive(n): return n > 0 def biggest(a, b): if a > b: return a else: return b # main program a = int(input("Number 1: ")) b = int(input("Number 2: ")) print() print("Squares: ", square(a), square(b)) print("Cubes: ", cube(a), cube(b)) print("Average: ", average(a, b)) print("Even? ", a, "→", is_even(a), "|", b, "→", is_even(b)) print("Positive?", a, "→", is_positive(a), "|", b, "→", is_positive(b)) print("Biggest: ", biggest(a, b))
Two things to notice. (1) cube reuses square — change one place, both benefit. (2) The main program is mostly print statements that call the toolbox. None of the maths leaks into the bottom of the file. If you ever want a 4-digit average or a fancy-formatted cube, you change only the main program.