Lab: Documentation And Exceptions
Exercise 1
Sometimes programmers write functions that are difficult to read. Let’s take a look at the following function.
def apple(orange, banana):
"""Given an orange and a banana, will return a pear"""
pear, kiwi = [], 0
while kiwi < len(orange) or kiwi < len(banana):
mango = pear + [5]
if kiwi < len(orange) and len(mango) > len(pear):
pear.append(orange[kiwi])
if kiwi < len(banana) or False:
pear.append(banana[kiwi])
kiwi = kiwi * 1 + (17 - 4*4)
return pear
a. Determine what the function is doing and give it a more appropriate name.
b. The variable names aren’t very helpful. Give them names that are more descriptive of what they are.
c. Clean up the function by removing any unnecessary code that does not serve a purpose.
d. Write a more appropriate docstring for the function and include the following sections
- A short one-line purpose statement
- A Parameters section listing the types of the parameters
- A Returns section briefly summarizing the return value and its type
- A Preconditions section if there are more restrictions on the input other than their type
- A Postconditions section that describes, in more detail, the exact relationship between the output and the inputs
Exercise 2
It is common to verify that the preconditions of your code are met and raise an exception if not. We will do this on the swap
function defined in a previous lab. Below I have checked that the parameters have the appropriate type and raised an exception otherwise:
def swap(lst, index1, index2):
"""Modifies the list so that the elements at index1 and index2 are swapped
Parameters:
lst: A list
index1: An integer
index2: An integer
Preconditions:
* len(lst) > 0
* 0 <= index1 < len(lst)
* 0 <= index2 < len(lst)"""
if type(lst) != list:
raise TypeError("first arg must be a list")
elif type(index1) != int:
raise TypeError("second arg must be an int")
elif type(index2) != int:
raise TypeError("third arg must be an int")
temp = lst[index1]
lst[index1] = lst[index2]
lst[index2] = temp
a. Add another elif
case that checks if the len(lst) > 0
precondition is satisfied and raises a ValueError
exception with an appropriate message if not.
b. Add one more elif
case that checks if index1
and index2
are within the correct range of indices, that is, there are in the range between 0 (inclusive) and len(lst)
(exclusive).
Exercise 3
Write a program called sqrt.py
that asks the user to enter a number and prints the square root of that number. However, instead of crashing with a TypeError
if the user enters a non-number, your program should handle the error by displaying a helpful error message and asking them to retype the number.
Exercise 4
Write a function called grid_points(n, k)
that takes two integers and returns a list of lists that consists of all the points [x,y]
where 0 <= x < n
and 0 <= y < k
. For example,
>>> grid_points(2,3)
[[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2]]
>>> grid_points(1,1)
[[0, 0]]
>>> grid_points(5, 1)
[[0, 0], [1, 0], [2, 0], [3, 0], [4, 0]]
Your grid_points
function should also raise a TypeError
exception if one of the parameters is the wrong type and a ValueError
if either parameter is less than or equal to zero. Be sure to give helpful error messages!
You should save your function in a file named grid_points.py
and include a docstring description of it that has
- A short one-line purpose statement
- A Parameters section listing the types of the parameters
- A Returns section briefly summarizing the return value and its type
- A Preconditions section if there are more restrictions on the input other than their type
- A Postconditions section that describes, in more detail, the exact relationship between the output and the inputs
- A Raises section that describes what exceptions it raises and under what conditions