Warm-up · Activity 1 of 7
Warm-up from module B2: what does this print?
total = 0
for n in range(1, 4):
total += n
print(total)// B3.1 · ~25 min · Beginner
After this lesson you can define a function with def, call it with arguments, hand a result back with return, and explain why a function without return gives None.
Lesson 1 of 5 in B3 Functions
You will be able to
Warm-up · Activity 1 of 7
total = 0
for n in range(1, 4):
total += n
print(total)Predict · Activity 2 of 7
def double(n):
n * 2
print(double(5))Practice · Activity 3 of 7
def area(width, height):
____ width * heightPractice · Activity 4 of 7
def set_score():
score = 100
score = 5
set_score()
print(score)Practice · Activity 5 of 7
Brain teaser · Activity 6 of 7
def first_even(numbers):
for n in numbers:
if n % 2 == 0:
return n
return -1
print(first_even([3, 7, 8, 10]), first_even([1, 5]))Apply · Activity 7 of 7
Check your work against this list
Read the worked example, then write the exercises. Your code runs in your browser or on your computer and is never uploaded.
Worked example
line_total works out the cost of one line of a receipt and returns it. print_line prints a line and calls line_total to get the number. Because line_total returns its result, the program can also add two lines up. The last call shows what print_line gives back: it only prints, so the result is None.
main.py
def line_total(price, quantity):
"""Return the cost of one receipt line."""
return price * quantity
def print_line(name, price, quantity):
"""Print one receipt line."""
print(name, quantity, "x", price, "=", line_total(price, quantity))
print_line("apples", 0.5, 6)
print_line("bread", 2.25, 1)
total = line_total(0.5, 6) + line_total(2.25, 1)
print("total:", total)
result = print_line("milk", 1.1, 2)
print("print_line returned", result)
Run it with
python main.pyOutput
apples 6 x 0.5 = 3.0
bread 1 x 2.25 = 2.25
total: 5.25
milk 2 x 1.1 = 2.2
print_line returned NoneTab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.
The first run downloads Python for your browser (up to 6.5 MB) and keeps it cached. Your code stays on your device.
Exercise 1 of 2
Complete two functions in main.py. area(width, height) returns width times height, and perimeter(width, height) returns the distance around the rectangle: two widths plus two heights. Both must return the number, not print it. The tests import them with from main import area, perimeter.
Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.
The first run downloads Python for your browser (up to 6.5 MB) and keeps it cached. Your code stays on your device.
Replace return 0 with the calculation; the parameters width and height already hold the numbers from the call.
The perimeter adds all four sides: width + height + width + height.
return width * height and return 2 * width + 2 * height.
One way to solve it. Yours can look different and still pass the checks.
def area(width, height):
"""Return the area of a rectangle."""
return width * height
def perimeter(width, height):
"""Return the perimeter of a rectangle."""
return 2 * width + 2 * height
print(area(3, 4), perimeter(3, 4))
Install Python 3.14 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.
main.py
def area(width, height):
"""Return the area of a rectangle."""
return 0 # replace with the real calculation
def perimeter(width, height):
"""Return the perimeter of a rectangle."""
return 0 # replace with the real calculation
print(area(3, 4), perimeter(3, 4))
test_main.py
from main import area, perimeter
def test_area():
"""area(3, 4) is 12"""
got = area(3, 4)
assert got == 12, f"area(3, 4) returned {got!r}, expected 12"
def test_area_other_sizes():
"""area works for 5 x 5 and 2.5 x 2"""
got = area(5, 5), area(2.5, 2)
assert got == (25, 5.0), f"area(5, 5) and area(2.5, 2) returned {got!r}, expected (25, 5.0)"
def test_perimeter():
"""perimeter(3, 4) is 14"""
got = perimeter(3, 4)
assert got == 14, f"perimeter(3, 4) returned {got!r}, expected 14"
def test_perimeter_square():
"""perimeter(5, 5) is 20"""
got = perimeter(5, 5)
assert got == 20, f"perimeter(5, 5) returned {got!r}, expected 20"
On macOS and Linux, type python3 wherever these commands say python, as in the first lesson.
Run the program:
python main.pyRun the checks (needs learnrun.py in the same folder):
python learnrun.py testDownload learnrun.pyExercise 2 of 2
grade(score) should return a letter for a score from 0 to 100: "A" for 90 and up, "B" for 80 and up, "C" for 70 and up, and "F" below 70. The starter prints instead of returning, so every call gives None. Fix it with an if, elif and else chain that returns the letter.
Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.
The first run downloads Python for your browser (up to 6.5 MB) and keeps it cached. Your code stays on your device.
Replace print("F") with a chain of tests. Each branch ends with return and a letter.
Start with the highest grade: if score >= 90: return "A". Then elif score >= 80, and so on.
The else branch returns "F", so every score gets a letter and no call returns None.
One way to solve it. Yours can look different and still pass the checks.
def grade(score):
"""Return the letter grade for a score from 0 to 100."""
if score >= 90:
return "A"
elif score >= 80:
return "B"
elif score >= 70:
return "C"
else:
return "F"
print(grade(85))
Install Python 3.14 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.
main.py
def grade(score):
"""Return the letter grade for a score from 0 to 100."""
# 90 and up: "A", 80 and up: "B", 70 and up: "C", below 70: "F".
print("F")
print(grade(85))
test_main.py
from main import grade
def test_returns_the_letter():
"""grade(95) returns A"""
got = grade(95)
assert got == "A", f"grade(95) returned {got!r}, expected 'A' (does the function return the letter, or only print it?)"
def test_boundaries():
"""90, 80 and 70 are A, B and C"""
got = grade(90), grade(80), grade(70)
assert got == ("A", "B", "C"), f"grade(90), grade(80) and grade(70) returned {got!r}, expected ('A', 'B', 'C')"
def test_fail():
"""69 and 0 are F"""
got = grade(69), grade(0)
assert got == ("F", "F"), f"grade(69) and grade(0) returned {got!r}, expected ('F', 'F')"
On macOS and Linux, type python3 wherever these commands say python, as in the first lesson.
Run the program:
python main.pyRun the checks (needs learnrun.py in the same folder):
python learnrun.py testDownload learnrun.pyprint(square(4))
def square(n):
return n * n
What Python prints
NameError: name 'square' is not definedWhy, and the fix
Python runs a file from the top. When it reaches square(4), the def below has not run yet, so the name square does not exist. Put every def above the code that calls it; usually all functions go at the top of the file.
def greet(name):
print("Hello,", name)
greet()
What Python prints
TypeError: greet() missing 1 required positional argument: 'name'Why, and the fix
greet has one parameter, so every call needs one argument: greet("Ada"). The message names the parameter that got no value. The next lesson shows how a default value makes an argument optional.
def double(n):
print(n * 2)
result = double(5) + 1
What Python prints
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'Why, and the fix
double shows 10 but returns nothing, so double(5) is None, and None + 1 is an error. NoneType is the type of None. Write return n * 2, and print the result where you call the function if you want to see it.
Python in the browser: Pyodide 314.0.7, MPL-2.0. Licence and source
5 questions, no hints. Score 80% or more to complete the lesson.
Finish every activity above to unlock the exit ticket.