SpiralTrain
Exercises › Block 1 · Exercise 3

Block 1 · Exercise 3

Functions

Starter notebook
03-functions-starter
Fabric path
/lakehouse/default/Files/data/solutions/03.functions/

Open the notebook 03-functions-starter in your workspace. It holds calculator4.py, from /lakehouse/default/Files/data/solutions/03.functions/starter/, in one cell : two numbers and a list of numbers at the top, and the calculations on them written out inline. Run it once and read what it prints.

Move each calculation into a function of its own, one part at a time, 1a, 1b and so on, and compare with the expected output before you go on. The output stays the same ; only the shape of the code changes. The solution is in 03-functions-solution, under every part on the exercise site, and at the back of the exercises PDF.

Step 1Arithmetic

1a

Write a function add(i, j) that returns the sum of two numbers. Replace the inline sum in the cell with a call to it. Put the function at the top of the cell, so it exists before the first call. Run the cell.

Hint 1

The slide Function Syntax shows the shape of def. The function needs a return, or the call gives back None.

Check your output
Add 7.0 and 2.0 : 9.0
Show solutionHide solution
python
def add(i, j):
    return i + j


f1 = 7.0
f2 = 2.0

addresult = add(f1, f2)
print(f"Add {f1} and {f2} : {addresult}")

1b

Write subtract, multiply and divide the same way, and replace the other three inline calculations with calls to them. The output has to be the same four lines as before.

Hint 1

subtract(f1, f2) is f1 - f2. The starter's label says Subtract 2.0 from 7.0, so mind the order of the two arguments.

Check your output
Add 7.0 and 2.0 : 9.0
Subtract 2.0 from 7.0 : 5.0
Multiply 7.0 by 2.0 : 14.0
Divide 7.0 by 2.0 : 3.5
Show solutionHide solution
python
def subtract(i, j):
    return i - j


def multiply(i, j):
    return i * j


def divide(i, j):
    return i / j


subtractresult = subtract(f1, f2)
print(f"Subtract {f2} from {f1} : {subtractresult}")
multiplyresult = multiply(f1, f2)
print(f"Multiply {f1} by {f2} : {multiplyresult}")
divideresult = divide(f1, f2)
print(f"Divide {f1} by {f2} : {divideresult}")

Step 2Number lists

The starter turns the string s into slist, a list of strings, and then sums it in a loop.

2a

Write a function convert_to_int_list(slist) that takes a list of strings and returns a list of integers. Call it on slist and print the result.

Hint 1

Build an empty list, go through slist, and add int(x) for every x. The list is what the function returns.

Check your output
[1, 2, 3]
Show solutionHide solution
python
def convert_to_int_list(slist):
    ilist = []
    for x in slist:
        ilist.append(int(x))
    return ilist


print(convert_to_int_list(slist))

2b

Write a function summate(ilist) that takes a list of integers and returns their sum. Replace the loop in the cell with a call to convert_to_int_list that gives intlist, and a call to summate that gives summation. The Average line at the bottom still uses summation. Run the cell.

Hint 1

Start a total at 0 before the loop, and add each number to it.

Check your output
Sum of list [1, 2, 3] is 6
Show solutionHide solution
python
def summate(ilist):
    s = 0
    for x in ilist:
        s = s + x
    return s


intlist = convert_to_int_list(slist)
summation = summate(intlist)
print(f"Sum of list {intlist} is {summation}")

2c

Write a function average(ilist) that returns the mean of a list of integers, and replace the starter's line average = summation / len(intlist) with a call to it. Keep no variable named average, or it hides your function.

Hint 1

average does not need its own loop. It can call summate.

Check your output
Average of list [1, 2, 3] is 2.0
Show solutionHide solution
python
def average(ilist):
    return summate(ilist) / len(ilist)


print(f"Average of list {intlist} is {average(intlist)}")

2d

The starter printed Sum of list ['1', '2', '3'], with quotes. Yours does not. Write a comment that says why.

Hint 1

Compare what the starter's loop appends to intlist with what convert_to_int_list puts in its list.

Show solutionHide solution
python
# The starter appended x to intlist before it was converted, so the list held strings.
# convert_to_int_list appends int(x), so the list holds numbers and prints without quotes.

Step 3Factorial

3a

Write a function faculty(n) that returns the factorial of n, which is n × (n-1) × (n-2) × ... × 1. The name is the one the rest of the course uses, from the Dutch faculteit. Write it recursively : the function calls itself with a smaller number. It returns 1 for 0 and for 1. Print faculty(5).

Hint 1

Every recursive function needs a case that stops the recursion, and a case that calls itself with a smaller argument.

Hint 2

The factorial of 5 is 5 times the factorial of 4.

Check your output
120
Show solutionHide solution
python
def faculty(n):
    if n == 0 or n == 1:
        return 1
    return n * faculty(n - 1)


print(faculty(5))

3b

Call faculty(-1) inside a try that catches Exception as error, and print type(error).__name__ and the message of the error.

Hint 1

Follow the calls by hand : which case does -1 reach, and what does it call next?

Check your output
RecursionError maximum recursion depth exceeded

The message can end with in comparison.

Show solutionHide solution
python
try:
    faculty(-1)
except Exception as error:
    print(type(error).__name__, error)

3c

Make faculty refuse a negative number with a ValueError and a message that names the number. Call faculty(-1) inside a try and print the message.

Hint 1

The refusal has to come before the recursion starts, on the first line of the function.

Check your output
faculty(-1) : no factorial for a negative number : -1

Your message may read differently.

Show solutionHide solution
python
def faculty(n):
    if n < 0:
        raise ValueError(f"no factorial for a negative number : {n}")
    if n == 0 or n == 1:
        return 1
    return n * faculty(n - 1)


try:
    faculty(-1)
except ValueError as error:
    print("faculty(-1) :", error)

3d

Call faculty(3000) inside a try that catches RecursionError, and print the message.

Hint 1

Every call waits for the call below it to finish, and Python allows only about a thousand of them at once.

Check your output
faculty(3000) : maximum recursion depth exceeded

The message can end with in comparison.

Show solutionHide solution
python
try:
    faculty(3000)
except RecursionError as error:
    print("faculty(3000) :", error)

If time permits

  • Give every function type hints, the way Exercise 2 did.

  • Replace summate and average with the built-ins sum and len, and check that the answers match.

  • Print the interactive calculator from the course data and read it :

    python
    from pathlib import Path
    
    folder = Path("/lakehouse/default/Files/data/solutions/03.functions/interactive")
    print((folder / "calculator5.py").read_text())

    It asks for each calculation with input() and calls the same functions, so it runs as a program in a terminal and not in a notebook. Trainer demonstration.

Tried it yourself first?

The solution is a spoiler. Work through the hints first : a wrong attempt teaches more than a solution you only read.