Week 8: Functions#

By the end of this class, you should be able to:

  • write a function in Python that takes arguments and returns a value

  • write a function that provides a default value for its arguments

  • describe how functions may be called with keyword (or named) argument

Functions#

  • We’ve seen many functions: sum(), max(), len(), and so on. We’re going to explore how to create our own functions.

  • We will start simple and then expand. We’re going to use Python’s random module, and in particular function randint().

  • Note that this is a different method than we used last week for rolling a die.

What’s a function?#

A function definition has 3 parts:

  1. Function signature (or headers):

    • def function_name():

  2. Documentation string or “docstring” for short.

    • Describes what the function does, the purpose of each argument and what the function returns.

    • Often gives an example of how to call the function

    • Is sometimes omitted for simple functions, but best practice is to always include it.

  3. Function body

    • A sequence of statement that perform the computation

    • If it ends with return result then the “result” of the function can be assigned to a variable.

import random

def roll_six_sided_die():
    ''' Simulate the roll of a six-sided die by returning a number 
        between 1 and 6
    '''
    roll = random.randint(1, 6)
    return roll

Now we can call our function:

roll_six_sided_die()
6

And we can can assign the return value of the function to a variable.

my_roll = roll_six_sided_die()
print(my_roll)
5

Arguments#

Now let’s add an argument to our function. Instead of just rolling a six-sided die, suppose I’m playing a TTRPG and want to be able to roll dice with different numbers of sides. We can pass the number of sides as an argument to the function.

def roll_die(num_sides):
    """Simulate a die roll by returning a number between 1 and num_sides.

        Arguments: num_sides (int): numbef of sides of the die to roll
    """
    roll_value = random.randint(1, num_sides)
    return roll_value
roll_die(20)
13

Note that we have to provide the arugment when we call the function.

roll_die()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[14], line 1
----> 1 roll_die()

TypeError: roll_die() missing 1 required positional argument: 'num_sides'

Local Variables#

In our function above, num_sides and roll_value are local to the function. They only exist while the function is running.

print(roll_value)
print(num_sides)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[15], line 1
----> 1 print(roll_value)
      2 print(num_sides)

NameError: name 'roll_value' is not defined

When do you write a function?#

If you find yourself copying and pasting code, it’s time to write a function that does the same thing.

If you think of a good domain-specific name for a computation you are doing, make a function so the rest of your code is more readable.

Follow the conventions for writing function names:

  • make all letters lowercase (so amount, not Amount or AMOUNT)

  • separate words with underscores so (tax_rate, not tax rate or taxrate)

You try it#

Write a function called above_threshold() that takes two arguments. Here is the docstring:

""" Return the number of elements of the temps that are higher than threshold

Arguments:
   temps (list) : A list of floating point numbers representing weekly temperatures
   threshold : A floating pointer number

Example: 
   above_threshold([1.0, 3.5, 2.0], 1.5) returns 2
"""
# write your code here

def above_threshold(temps, threshold):
    """ Return the number of elements of the temps that are higher than threshold

    Arguments:
        temps (list) : A list of floating point numbers representing weekly temperatures
        threshold : A floating pointer number

    Example: 
        above_threshold([1.0, 3.5, 2.0], 1.5) returns 2
    """
    count = 0
    for t in temps:
        if t > threshold:
            count += 1
    return count

Now call it and check whether it produces the correct answer.

above_threshold([1.0, 3.5, 2.0], 1.5)
2
help(above_threshold)
Help on function above_threshold in module __main__:

above_threshold(temps, threshold)
    Return the number of elements of the temps that are higher than threshold

    Arguments:
        temps (list) : A list of floating point numbers representing weekly temperatures
        threshold : A floating pointer number

    Example:
        above_threshold([1.0, 3.5, 2.0], 1.5) returns 2

Keyword Arguments#

So far we have been calling our functions using positional arguments. roll_die() took one argument and above_threshold() took two.

Notice that we can’t call above_threshold() and reverse the order of the arguments.

above_threshold(1.5, [1.0, 3.5, 2.0])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[19], line 1
----> 1 above_threshold(1.5, [1.0, 3.5, 2.0])

Cell In[16], line 14, in above_threshold(temps, threshold)
      4 """ Return the number of elements of the temps that are higher than threshold
      5 
      6 Arguments:
   (...)     11     above_threshold([1.0, 3.5, 2.0], 1.5) returns 2
     12 """
     13 count = 0
---> 14 for t in temps:
     15     if t > threshold:
     16         count += 1

TypeError: 'float' object is not iterable

However, we can reverse the order if we name the arguments:

above_threshold(threshold = 1.5, temps =[1.0, 3.5, 2.0])
2

When we define a function we can also give an argument a default value. Let’s use our roll_die() function as an example:

def roll_die(num_sides = 6):
    """Simulate a die roll by returning a number between 1 and num_sides. 
       The default value of num_sides is 6

        Arguments: num_sides (int): number of sides of the die to roll
    """
    roll_value = random.randint(1, num_sides)
    return roll_value
# Now call it

# we can pass in an argument
roll1 = roll_die(20)
print(roll1)

# or call it without an argument and use the default
roll2 = roll_die()
print(roll2)
19
2

You can combine positional arguments and keyword arguments in more complicated ways, but we are going to keep it simple for this course. The main reason to show you keywork arguments is so that you recognize them in the pandas and matplotlib methods we are using.