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 | +----------------------+--------------------------------------------------------+ .. topic:: What to Submit Submit your script(s) for the final task of this exercise. These script should be named *[your surname]_e003_functions.[ext]* and *[your surname]_e003_main.[ext]*, where *[ext]* is the file extension. In case of Python, this would be *.py*, for Matlab it is *.m*, etc. 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: .. code-block:: python 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. .. figure:: cashier_cc0.jpg The calculation of your total cost can be thought of as a function: .. code-block:: python 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. .. literalinclude:: cashier.py 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: .. code-block:: python 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: .. code-block:: python 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. .. code-block:: python 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: .. code-block:: python 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: .. code-block:: python 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. .. literalinclude:: unitConverter.py 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. .. code-block:: python 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!