Python Function Exercises With Solutions

One of the first things to master as a newcomer to Python is the skill of writing functions. Like everything else in programming, skills are developed through practicing. These beginner-focused exercises contain complete solutions to help you if you get stuck and to show you how we would approach the problem.

It’s strongly recommended that you try these exercises out first before looking at the solutions. If you want to try these out in Jupyter notebook, we’ve include an online notebook that contains only the exercises – you can work on these online without installing anything.

  1. Using a loop (that is, without using a slice), write a function “reverse_list” and takes a list as input and returns a copy of the list in which all the elements have been swapped (the first element with the last, the second with the next to last, etc.) Test that it works correctly for the following lists:

odd_length = [23, 4, 9, 6, 8, 22, 18]
even_length = [6, 5, 2, 9, 44, 12]
empty_list = []

Solution:

def reverse_list(input: list) -> list:
    """returns a reversed copy of list, leaving original list unchanged"""
    half_list = int(len(input) / 2)
    output = input.copy()
    for idx in range(0, half_list):
        output[idx] = input[len(input) - 1 - idx]
        output[len(input) - 1 - idx] = input[idx]
    return output

# Test as instructed
odd_length = [23, 4, 9, 6, 8, 22, 18]
even_length = [6, 5, 2, 9, 44, 12]
empty_list = []
assert reverse_list(odd_length) == [18, 22, 8, 6, 9, 4, 23]
assert reverse_list(even_length) == [12, 44, 9, 2, 5, 6]
assert reverse_list(empty_list) == empty_list

# Ensure orginal unchanged
assert odd_length == [23, 4, 9, 6, 8, 22, 18]

2. Write a function that takes in a string and returns the string with all the vowels
removed. Test it using the following code (you should see no output):

assert remove_vowels("We all love Python!") == "W ll lv Pythn!"

Solution:

def remove_vowels(string):
    """Returns a string with the vowels removed."""
    vowels = "aeiouAEIOU"
    new_string = ""
    for char in string:
        if char not in vowels:
            new_string += char
    return new_string

assert remove_vowels("We all love Python!") == "W ll lv Pythn!"

3. Write a function that takes in a list of integers or floats and returns True if the list contains duplicates and False if the list does not contain duplicates. Use a type hint to “enforce” the correct type.

Solution:

def has_duplicates(items: list[int|float]) -> bool:
    """Checks the list and returns true if there are duplicate values."""
    return len(set(items)) < len(items)

# Test
assert not has_duplicates([1,2,3,4])
assert has_duplicates([1.0, 2.0, 3.3, 3.3])

4. Write a function to print all the powers of two, up to and including the twelfth power. The output should look like this:

2 to the power of 0 = 1
2 to the power of 1 = 2
# ...

Use a while loop to control the iteration and printing.

Solution

def print_powers_of_two():
    """Print two raised to a number, for numbers in range 0 to 12, inclusive"""
    exponent = 0
    LAST = 12
    while exponent <= LAST:
        print(f"2 to the power of {exponent} is {2**exponent}")
        exponent += 1

print_powers_of_two()

5. Write a new function to calculate the same values as we did in #4. This time, write a function named calculate_values to return numbers raised to a power of two in a list, again beginning at 2 to the zero power and ending at 2 to the 12th power as before. Call the function and test the returned list this way:

values = calculate_values()
print(values)
assert values[0] == 1
assert values[-1] == 4096

You should see the list values and no other output.

Solution

def calculate_values():
    LAST = 12
    return [2**exponent for exponent in range(0, LAST+1)]

values = calculate_values()
print(values)
assert values[0] == 1
assert values[-1] == 4096

6. Write a function with the following signature:

def display_box(width: int, height: int, character="*")

This function will draw a simple ASCII-art rectangle (non-filled) of the given height and width, using character to print the lines. For example, display_box(5, 4, 'x') should output the following:

xxxxx
x   x
x   x
xxxxx

The function should raise an exception if the dimensions are less than 2 wide by two high.

Solution

def display_box(width: int, height: int, character="*"):
    if width < 2 or height < 2:
        raise Exception("Box dimensions must be at least 2 x 2")
    line = 0
    while line < height:
        # First or last line
        if line == 0 or line == height - 1:
            print(character * width)
        else:
            print(character + " " * (width - 2) + character)
        line += 1

# Try testing with different values, e.g.
display_box(5, 4, 'x')

7. This exercise is famous, and a perhaps one of the most popular “can you handle basic programming” interview questions. Write a function, fizzbuzz, with a single integer argument named value. If the value is evenly divisible by three, return the string “fizz”. It the value is evenly divisible by five, return the string “buzz”. If the value is evenly divisible by both three and five, return fizzbuzz. Finally, if none of these apply, return an empty string.

Test it with the following code:

values = [3,6,9,11,5,10,20,23,15,30,60]
for value in values:
    print(fizzbuzz(value))

Solution

def fizzbuzz(value: int) -> str:
    result = ""
    if value % 3 == 0:
        result += "fizz"
    if value % 5 == 0:
        result += "buzz"
    return result
    
values = [3,6,9,11,10,20,40,23,15,30,60]
for value in values:
    print(fizzbuzz(value))

Test output:

fizz
fizz
fizz

buzz
buzz
buzz

fizzbuzz
fizzbuzz
fizzbuzz

8. There are six New England states: Rhode Island, Connecticut, Massachusetts, Maine, Vermont, and New Hampshire. Their postal abbreviations are RI, CT, MA, ME, VT, and NH, respectively.

Write a function that takes a New England state code as a string and returns a string with the longer name as shown above. Return None if no mapping is found.

Solution

Whenever an exercise calls for mapping one value to another, think “dictionary”! Once you realize that, the function boils down to creating the dictionary and passing the key (in this case, the state code), to the get function. (Get is convenient since it will return None by default if the key is not found rather than throwing an exception).

def get_state_full_name(state_code: str) -> str:
    """Maps a state code to a full name for New England States only"""
    states = {
        "RI": "Rhode Island", 
        "CT": "Connecticut",
        "MA": "Massachusetts",
        "ME": "Maine",
        "NH": "New Hampshire",
        "VT": "Vermont"}
    return states.get(state_code.upper())

9. Speaking of interview questions, here’s another fairly simple one we used to ask developers who interviewed for our small team. We were doing Java, but the question works equally well in Python, so I’ve translated it here.

Suppose you have a list of movie objects, which are defined as follows:

class Movie:
    def __init__(self, title, director, year_released):
        self.title = title
        self.director = director
        self.year_released = year_released

Write a function that takes a list of movies and displays the title and director of each movie in the list.

Solution

Here’s a reasonable solution one could code in an interview that includes an informal test to demonstrate the function.

  class Movie:
    def __init__(self, title, director, year_released):
        self.title = title
        self.director = director
        self.year_released = year_released
        
def display_movies(movies: list[Movie]) -> None:
    """Displays movie title and director, one per line"""
    for movie in movies:
        print(f"'{movie.title}'. Directed by {movie.director}.")

movies = [Movie("Full Metal Jacket", "Stanley Kubrick", 1987), 
          Movie("Star Trek II: The Wrath of Khan", "Nicholas Meyer", 1982)]

display_movies(movies)

Output:

'Full Metal Jacket'. Directed by Stanley Kubrick.
'Star Trek II: The Wrath of Khan'. Directed by Nicholas Meyer.
  1. A certain print order costs \(3.00 per copy for orders of less than ten copies, \)1.25 for for orders of 10-99 copies, and $0.90 per copy for orders of 100 copies or more. Write a function that returns a total price for the order.

Solution

Note that in the solution below, we use descriptive names to clarify the pricing and price cutoffs. This makes the function longer but clarifies our intent and makes it easier to change prices or cutoffs if the business requirements change.

def calculate_price(copies: int):
    """Calculate price of a print order based on cutoffs"""
    small_order_rate = 3.00
    medium_order_rate = 1.25
    large_order_rate = .90
    
    minimum_medium_order = 10
    minimum_large_order = 100
        
    if copies < minimum_medium_order:
        return copies * small_order_rate
    elif copies < minimum_large_order:
        return copies * medium_order_rate
    else:
        return copies * large_order_rate
  1. The velocity of an object falling near the earth is given as -9.81 meters per second squared. (It’s negative because the object is falling downwards, so it’s relative to where it started). Write a function that takes two arguments, a whole number of seconds since the object was released and a starting height in meters. Return a boolean value that’s True if the object would still be accelerating, or False it it already hit the ground.

Solution

def still_falling(seconds_ago: int, starting_height: float):
    """Returns true if an object dropped so many seconds ago would still be falling"""
    distance = -9.81 * seconds_ago**2
    return starting_height + distance > 0