P1-E003

In this exercise, you will learn about writing your own functions and using them in an efficient way.

Information

Learning goals

Concepts

  • functions

Skills

  • use functions from existing modules

  • write your own function with specified i/o

  • save functions in script

Functions from Modules

In exercises E001 and E002, you learnt the basics of programming. With the concepts introduced in E001 and E002, you are able to perform any calculation and solve virtually any mathematical problem. However, the code will become very messy very quickly if you only ever call on those primitive methods. In this exercise, you learn about writing and using your own functions. You may recall that we already used functions in exercise E001 when we calculated the sin, for example:

import math as mt
mt.sin(2.0)

Imagine having to manually code this calculation with loops and if statements - possible, but inefficient, since we need to carry out this type of calculation a lot. Instead, this function has been written and packaged in the math module, which you can then import to use the sin() function and other functions included in the module.

Cashier Function Example

While we touched on the concept of arguments in functions before, it is now time to look in more detail into functions. A function is a unit of code that performs a specific task based on so called input arguments, i.e. options and values you pass to the function when calling it, to calculate and return one value. A useful analogy for this is a cashier desk at a store.

../../_images/cashier_cc0.jpg

The calculation of your total cost can be thought of as a function:

total = cashierFunction(productlist)

First, you pass a list of products, corresponding to input arguments, to the cashier. Internally, the cashier or their computer then looks up the prices for the passed products and sums these up. This step corresponds to the specific task/computation within a function. Finally, the function has the total and returns this one value as output back to you.

Let’s look at an implementation of this. Examine the code (and the comments) below.

# This pythong script contains a function to lookup product prices for passed products and a function sum these up to return the total.
#
# This is a dictionary of product prices. It is not part of any specific function below and can therefore be accessed from anywhere in the script.
productPriceDict = {'apples':1.50,'doggeFood':2.99,'myPhone18':99999.99,'freedomFromCapitalism':0.0}
#
# function looks up the prices of products
def lookupPrice(product): 
    price = productPriceDict[product]               # loop up the price of a product based on the passed product name and the price dictionary
    return price                                    # return the price to the script/code block that called this function
#    
# this function calculate the total based on passed product list
def calculateTotal(productList):   
    total = 0.0                                     # explicitly set the total to zero before summing up prices
    for i in range ( len(productList) ):            # loop through the list of products
        total = total + lookupPrice(productList[i]) # update the total by looking up the price of the product and adding it to the total
    return total                                    # return the total to the script/code block that called this function 

You start defining a function with the def statement. Note that in Python, just as is the case for loops and if statements, you do not need to explicitly declare an end to the function. Instead, the indented block of code following the def statement is interpreted as code belonging to the function. You may have noticed that we have 2 functions in here:

  • 1: lookupPrice() - this one looks up and returns the price of a product based on the product name that is passed to the function as an argument.

  • 2: calculateTotal() - this one calculates the total based on the list of product names that is passed to the function. This function uses the lookupPrice() function above.

Now let’s have a look how you would use this. Copy the code above into your code editor and save it as cashier.py. In your console, create a list of products. These must be in the product dictionary. (Feel free to expand this). One example could be:

products = ['apples', 'apples', 'doggeFood']

This is the list of products that serves as input for our function to calculate the total. Just as you did for the math module, import your cashier.py script to access the functions within it. Then, call the function to calculate the total, pass your product list to the function as an argument, save the returned value of the function in the totalToPay variable and display it with the print function:

import cashier
totalToPay = cashier.calculateTotal(products)
print(totalToPay)

Feel free to paly around with the product list, price dictionary and other code to get a better grasp of what is happening here. Not every function has to return a value. You can also use functions as procedures that return no value. For example, if you know that you always want your total to simply be displayed and not used in further calculations, you may modify the calculateTotal function by removing the return statement and instead add a line of code to print the total. Append this modified function to your cashier.py file.

def calculatePrintTotal(productList):
    total = 0.0                                     # explicitly set the total to zero before summing up prices
    for i in range ( len(productList) ):            # loop through the list of products
        total = total + lookupPrice(productList[i]) # update the total by looking up the price of the product and adding it to the total
    print(total)                                    # display total

Note that we have given the function a different name. Save the file, create a new product list and call the new function:

import cashier
products = ['apples', 'apples', 'doggeFood']
cashier.calculatePrintTotal(products)

The total was again displayed, because it was printed in the function instead of outside the function. If you attemped to now get the total from the new function and print it by typing:

totalToPay = cashier.calculateTotal(products)
print(totalToPay)

You will get a None. This is because in our new function, we do not return a value. Therefore, no value will be passed to the variable total.

Unit Converter Module

Let’s bring this back to atmospheric science and implement a module for unit conversion. This module will consist of several functions and will save you a lot of time and code lines in your main programme.

# This is a module consisting of several function to convert units. This will also demonstrate the concept of nested functions.

# convert()
# ---------
# This is main function called by external script. It takes 3 input arguments:
# 1. value       - the value (floating point number) you wish to convert
# 2. currentUnit - the unit the value you passed 
# 3. targetUnit  - the unit you want your output value to be in 
# 
# It will call the appropriate converter based on the input arguments and 
# return the convertedValue. 

def convert(value, currentUnit, targetUnit):

    # k2c()
    # ---------
    # This function converts Kelvin to Celsius.
    # Input (argument): value in Kelvin
    # Output (returned): value in Celsius
    def k2c(value):
        return value-273.15

    # c2k()
    # ---------
    # This function converts Celsius to Kelvin.
    # Input (argument): value in Celsius
    # Output (returned): value in Kelvin
    def c2k(value):
        return value+273.15
    
    # Here we determine which of the converted functions will be called
    if currentUnit == 'K' and targetUnit == 'C':
        convertedValue = k2c(value)
    elif currentUnit == 'C' and targetUnit == 'K':    
        convertedValue = c2k(value)        
    else:
        print("Invalid arguments")
        
    # return the converted value                
    return convertedValue

Note that this module consists of several function, and the actual converters k2c and c2k are functions nested in the main convert function. This means they only exist within the convert function. Save this block of code as unitConverter.py and use it via the console as we used the cashier function above.

import unitConverter                         # import the unit converter
print(unitConverter.convert(10.3,'K','C'))   # convert 10.3 from degrees Kelvin to degrees Celsius

Now it’s time to flesh out the module a little. Add additional functions for conversion, e.g. converting mm/d to mm/a and vice vera, come up with new, necessary input arguments and make sure that the convert() function selects the appropriate converter.

Your Task

Rememer last week’s assignment? You wrote code that is able to calculate the mean grade based on a list of grades g. Wouldn’t it be great if all you had to do was to pass the list of grades to a function and it would return the mean to you? Restructure last weeks code and put your different methods for calculating the mean grade into a python file as functions. When implementing your mean functions:

  • write one function for each way to calculate the mean grade

  • think about the necessary input arguments and the decision process to call one of the two (or more) mean functions

Additionally, write a script that defines a list of grades, imports your functions as a module and uses your implemented functions to calculate the mean grade. Make sure your code works!

When you are happy with your code, name your files [your surname]_e003_functions.[ext] (for the scripts containing your functions) and [your surname]_e003_main.[ext] for your script calling the functions, zip them and submit them via ILIAS.

Warning

Late submissions won’t be accepted!