Generalizing Functions to Be More Reusable

In a previous tutorial on functions, I utilized the example below with bike trips data and a function to calculate the duration of all trips in seconds.

But, it wasn't perfect.

Inside the function, I utilized an index of 0 so I could iterate over the first index of trip duration values in each inner list.

However, we can make that function better by making it more generalizable so the function can serve multiple purposes. To make it more generalizable, let's allow the function to take an additional argument for an index value of our inner lists (each representing a ride).

Bike Trips Example

Sample Data

Below is a sample of data for bike trips as a list of lists. Each inner list holds the data for a trip formatted as [duration in seconds, date].

bike_trips = [[475, '2018-02-18'],
              [825, '2018-02-18'],
              [1034, '2018-02-18'],
              [980, '2018-02-18'],
              [1350, '2018-02-19'],
              [1880, '2018-02-19'],
              [1950, '2018-02-19'],
              [1530, '2018-02-19']
             ]

I previously created a function to find the sum of seconds biked on a given day.

Old function to calculate sum of trip durations on a day

# global variables below can be used in any function
index_trip_duration_seconds = 0
index_trip_date = 1


def sum_seconds_biked_day(ride_date):
    """
    Find the sum of seconds biked on a given day

    Keyword argument:
    ride_date -- date (string in format year-month-day)
    """
    sum_trips_seconds = 0
    for trip in bike_trips:
        if trip[index_trip_date] == ride_date:
            sum_trips_seconds += trip[index_trip_duration_seconds]

    return sum_trips_seconds

New more generalizable function to calculate the sum over an index in our inner lists

def sum_of_index_value(ride_date, index_value):
    """
    Find the sum through iteration over an index value in a list of lists

    Keyword argument:
    ride_date -- date (string in format year-month-day)
    index_value -- index of inner list (int)
    """
    sum_values = 0
    for trip in bike_trips:
        if trip[index_trip_date] == ride_date:
            sum_values += trip[index_value]

    return sum_values

Application of New Function

Let's say our bike_trips data structure is improved upon to add miles ridden with each ride.

Each inner list now holds the data for a trip formatted as [duration in seconds, miles ridden, date].

bike_trips = [[475, '2018-02-18', 1.8],
              [825, '2018-02-18', 3.2],
              [1034, '2018-02-18', 4.5],
              [980, '2018-02-18', 3.9],
              [1350, '2018-02-19', 5.1],
              [1880, '2018-02-19', 7.3],
              [1950, '2018-02-19', 6.3],
              [1530, '2018-02-19', 5.4],
              [1350, '2018-02-19', 4.0],
              [2345, '2018-02-20', 7.0],
              [2353, '2018-02-20', 6.4]
             ]

Create a new variable to assign miles ridden to an index value.

index_miles_ridden = 2

Apply sum_of_index_value to calculate sum of trip durations

When a function has more than a few numeric arguments, it is easy to forget what they are, or what order they should be in. In that case it is often a good idea to include the names of the parameters in the argument list: polygon(bob, n=7, length=70) These are called keyword arguments because they include the parameter names as “key- words” (not to be confused with Python keywords like while and def). This syntax makes the program more readable. It is also a reminder about how arguments and parameters work: when you call a function, the arguments are assigned to the param- eters.

Now that are function takes two arguments, I like to include the names of the parameters in the argument list. This helps with readability.

These are called keyword arguments because they include the parameter names as keywords.

sum_of_index_value(ride_date='2018-02-18', index_value=index_trip_duration_seconds)
3314

Apply sum_of_index_value to calculate sum of miles ridden

sum_of_index_value(ride_date='2018-02-18', index_value=index_miles_ridden)
13.4

Our new function now serves two (or more) purposes, instead of just one.