return: getting an answer back
Every function you wrote in the last lesson printed something. None of them gave you anything. That difference is small to write and large to understand, and it catches nearly everyone.
The problem
Here is a function that looks finished:
def add(a, b):
print(a + b)
total = add(2, 3)
print(total)
5 None
The 5 came from inside the function. Then print(total) printed None —
Python's word for "no value at all", which you met when append handed nothing
back in the lists lesson.
add put a number on the screen and gave nothing to the program. total holds
that nothing.
return
def add(a, b):
return a + b
total = add(2, 3)
print(total)
5
One word changed and the function now hands a value back to whoever called it.
add(2, 3) does not print 5 — it becomes 5, and can be used anywhere a 5
could be used:
def add(a, b):
return a + b
print(add(2, 3))
print(add(2, 3) * 10)
scores = [add(1, 1), add(2, 2)]
print(scores)
5 50 [2, 4]
None of that is possible with a function that only prints.
print is for people, return is for programs
That is the whole rule, and it is worth memorising:
printputs characters on a screen. A human reads them. The program cannot.returnhands a value back into the program. Code can use it. Nobody sees it unless you print it.
A function that only prints is a dead end — it can never be part of a bigger calculation.
return stops the function immediately
Nothing after a return runs:
def check(age):
if age >= 18:
return "adult"
return "minor"
print(check(20))
print(check(11))
adult minor
Follow check(11): 11 >= 18 is False, so the if block is skipped and the
last line runs. Follow check(20): the condition is True, return "adult"
runs, and the function ends right there — the final line never happens. That is
why no else is needed.
Useful, and also a trap:
def total(scores):
running = 0
for score in scores:
running += score
return running
return running
print(total([1, 2, 3]))
1
The return is inside the loop, so the function ends on the very first pass.
Expected 6, got 1. When a loop seems to run only once, check the indentation of
your return.
def total(scores):
running = 0
for score in scores:
running += score
return running
print(total([1, 2, 3]))
6
Same lines, one moved out a level.
Returning other things
Anything can be returned — a string, a list, a dictionary, a True or False:
def is_pass(score):
return score >= 50
def grade(score):
if score >= 80:
return "A"
elif score >= 65:
return "B"
return "C"
print(is_pass(72))
print(grade(72))
True B
A function returning True or False reads beautifully inside an if,
because the call is the condition:
def is_pass(score):
return score >= 50
for score in [82, 45, 60]:
if is_pass(score):
print(f"{score}: pass")
else:
print(f"{score}: fail")
82: pass 45: fail 60: pass
Notice there is no if is_pass(score) == True. is_pass(score) is already
True or False; comparing it to True adds nothing.
Building things out of small functions
Once functions return values, they combine:
def average(scores):
return sum(scores) / len(scores)
def grade(score):
if score >= 80:
return "A"
elif score >= 65:
return "B"
return "C"
marks = [88, 76, 91]
print(average(marks))
print(grade(average(marks)))
85.0 A
grade(average(marks)) — the inside runs first, and its answer goes straight
into the outside. Each function does one small job and knows nothing about the
other. That is what people mean when they say code is well designed, and it
starts with return.
Prefer learning with a teacher?
WasiLearn Academy runs small-group classes covering this material, online and in Karachi.
See the classes