========= Functions ========= Introduction ------------ In the previous lab, you were exposed to functions. You called functions that were provided, but you did not write any functions yourself. In this lab, you will write your own functions. By the end of this lab, you should be able to: #. write simple functions and #. call them from the interpreter and other functions. The concepts required for this lab are discussed here_. We encourage you to try the exercises before you look at the explanation. Getting started --------------- .. include:: includes/getting-started-labs.txt Revisit Real Valued Functions and Plots --------------------------------------- The ``lab3`` folder contains an enhanced solution to the plotting question from the previous lab. You will now write some new functions to plot different mathematical functions. #. Open ``ipython3`` in one window and the file ``plot_lab.py`` in your editor in another window. #. Look at the functions ``sinc`` and ``plot_sinc``. Try calling these functions in the interpreter (that is, in ``ipython3``): .. code:: In [2]: sinc(1.0) Out[2]: 0.8414709848078965 In [3]: sinc(5.3) Out[3]: -0.1570315928724342 In [4]: plot_sinc(-10.0, 10.0, 0.01) #. Write a function ``square`` that takes a floating point value ``x`` and returns ``x * x``. Run ``plot_lab.py`` in the interpreter again, and give your new function a try. #. Write a function ``plot_square`` that plots the new ``square`` function. You do not need to write this function from scratch; you can simply make a copy of the ``plot_sinc`` function, change the name to ``plot_square``, update the docstring, replace the call to ``sinc`` and update the arguments to ``pylab.title`` and ``pylab.ylabel``. Then call ``plot_square`` in the interpreter. How does the plot differ from the plot of the ``sinc`` function? (Remember to save the changes to your file and to re-run it in ``ipython`` before your try out your new code.) #. You will notice that the code for ``plot_square`` and ``plot_sinc`` have a lot in common. Keeping multiple copies of the same code almost always creates trouble. You may fix a bug in one copy but forget to fix it in the other, or find you need a third or fourth version of it. When you find yourself repeating code you should extract the common code into a function. Pull out the code that plots the figure into a new function. What arguments and how many of them should this function take? You need to write one new line of code for the new function: a function header. The rest of the body of the function can be copied directly from ``plot_sinc`` and then modified to replace the constants with parameters. #. Rewrite ``plot_sinc`` and ``plot_square`` to use this new function. ``plot_sinc`` and ``plot_square`` should now be much smaller and simpler. Creating more ``plot_whatever`` functions should now be much easier now too. You'll notice that there is still a fair amount of code that is repeated in ``plot_sinc`` and ``plot_square``. In fact, the only difference between the two functions is the call to ``sinc`` versus ``square``. You'll see in a few weeks that we can write functions that take other functions as parameters, which will allow us to abstract more and further alleviate the need for repeated code. Geometry -------- In this section you will be asked to write several functions from scratch. You will need to decide what the function requires as input and what it produces as an output. A point in the real plane can be described by an x and y coordinate, written mathematically as the point (x, y). A line segment can be described by two points (x1, y1) and (x2, y2). The length of a line segment can be found by computing the following mathematical formula: .. math:: \sqrt{(x_1 - x_2)^2 + (y_1 - y_2)^2} In this section you will create functions to compute the distance between two points and a function to compute the perimeter of a triangle. You will see how one function can be used by another. Open the file ``geometry.py`` in an editor. #. What types can we use to describe a point in Python? What effect does the choice of type have on the number of variables we need to represent a point? #. Consider a function ``dist`` that takes in arguments that describe two points and returns one value that is the distance between those two points. Write the function header for the function ``dist``. If you're not sure how to write the header then ask for help. It is important to get this code right before you move on. #. After you have written the function header, write the body of the function. Be sure to ``return`` the correct value. You will need to use the function ``math.sqrt``, which takes a ``float`` as an argument and returns its square root as a ``float``. #. Verify that your code works by using ``dist`` in the interpreter with a simple example. For example, compute the distance between the points ``(0, 1)`` and ``(1, 0)``. You should get a number very close to ``1.414``. 6. Repeat steps 2, 3, 4 with a new function named ``perimeter`` that takes in enough information to describe three points that define a triangle and returns the perimeter of that triangle. Do not call ``math.sqrt`` within the body of the ``perimeter`` function. Useful List Functions --------------------- Open the file ``list_exercises.py`` in an editor. #. Write your name at the top of ``list_exercises.py``. #. Write a function ``any`` that takes a list of booleans as arguments and returns ``True`` if any of the entries in the list is ``True``, and ``False`` otherwise. Add code to the function named ``go`` to test your function on a few different lists. Recall that you can initialize lists directly to generate test cases. For example:: test_list = [True, True, False, True, True] #. Write a function ``add_lists`` that takes two lists of the same length as arguments and adds corresponding values together ``[a[0] + b[0], a[1] + b[1], ...]``. The function should return a *new* list with the result of the addition. (Your code may assume that the lists are of the same length.) Add calls to your function to ``go()``. Try out different types for the elements. What happens if the elements are integers? What happens when they are strings? What happens if the lists are of mixed types (for example, ``[5, "a", 3.4"]``) #. Write a function ``add_one`` that takes a list and adds ``1`` to each element in the list. This function should update the input list, not create a new one. What value is printed by the following code? .. code:: a = [1, 2, 3, 4, 5] add_one(a) print(a) When Finished ------------- .. include:: includes/finished-labs-1.txt .. code:: git add plot_lab.py git add geometry.py git add list_exercises.py git commit -m "Finished with lab3" git push .. include:: includes/finished-labs-2.txt .. _here: understanding-functions.html