## Tutorial 5. Introduction to functions


Created by Emanuel Flores-Bautista 2019.  All content contained in this notebook is licensed under a [Creative Commons License 4.0](https://creativecommons.org/licenses/by/4.0/). The code is licensed under a [MIT license](https://opensource.org/licenses/MIT).


```python
import numpy as np
import pandas as pd
import seaborn as sns
import scipy.stats as stats
import matplotlib.pyplot as plt
import TCD19_utils as TCD

TCD.set_plotting_style_2()

# Magic command to enable plotting inside notebook
%matplotlib inline
# Magic command to enable svg format in plots
%config InlineBackend.figure_format = 'svg'
```

The purpose of programming is to make our life easier by speeding up the process of making certain operations on data. So far we've used pre-built and customed made functions, but we still have to understand the structure and syntax of functions in python. **Functions** make code reusable and thus is one of the most useful parts of coding. From now on, we will focus on making functions after we've made our data analysis workflows in our  jupyter notebooks. 

## Structure and syntax of customized functions in python

As we saw in the previous module, we can think of computational functions  the same way we think of math functions. Functions have **arguments** as inputs, they perform certain operations based on the arguments, and then **returns** and output. 

Let's think of a simple function that makes the summation operation. 


\begin{align}
f(x)= SUM(X) =  \sum_{i=1}^{n} x_{i} = x_{1} + x_{2} + ... + x_{n}
\end{align}

The function above takes in a vector $X$ as argument, and returns the sum over all of its elements. 

To code it in python, the function has to be **defined** using the `def` keyword, followed by the function's name (automatically colored in blue) and a colon. The [PEP-8](https://realpython.com/python-pep8/) guideline recommends to name functions with more than one word should be linked by underscores (e.g. `my_function`). 

After the colon, if you click enter, python automatically makes an [indentation](https://en.wikipedia.org/wiki/Indentation_style). After that it is highly recommended to have a doc string with a brief description of the function, its arguments, and its outputs. The doc string is usually written inside triple quotes. Furthermore, after the doc string, there is a block of code which is the operation of the function and finally, to get the result of the function, you need to write `return` and the name of the variable of your output, without parenthesis.

Thus the basic style of a function is the following:

    def my_function_name(args):
    
        """Docstring explaining the function"""
        block of code

        return result
        
Now we can write down the function of our summation function.       


```python
def summation(x):
    
    """
    Takes in a list or array and returns the sum of its elements. 
    """
    result = 0
    
    for element in x: 
        
        result += element
        
    return result
```

That's it, we can now call our function.


```python
summation(np.array([1,2,3]))
```

Luckily, there are a whole bunch of built-in mathematical functions inside numpy and scipy and we can readily use. In general, if you want to do something that seems really common, someone has probably already coded it in python.  

For example, the numpy module have built-in **methods** for the sum, mean, median, standard deviations and other operations in numpy arrays. To call this method we just have to write the dot syntax as everything in python is an object.  


```python
x = np.array([1,2,3])

x.sum()
```


```python
summation(x) == x.sum()
```

## Built-in functions

Beside the functions inside the different python packages, python has several built-in functions. We have already seen functions like `len()`, `sorted()`, `max()`, `range()`, `print()`, `reversed()`, in addition to data type conversions like `list()`. The complete list of built-in functions can be found in this [link](https://docs.python.org/3/library/functions.html). 

Another good programming conventions is the following:

> Never name a function with the same name as a python built-in function. 

## Functions don't need to have arguments

After writing functions, it is also useful to know that you can build your own modules to avoid pasting functions to a notebook and making undesirably long notebooks. A module is contained in a file that ends in `.py`. Let's explore the little module I made for the workshop. We can load the `.py` file into the notebook using the `%load` command. After running it, it will become commented out followed by a hash. You can also comment out the `import` statements in order to speed up the processing.



```python
%load TCD19_utils.py
```

As you can see the plotting functions contained do not have arguments. This is an example to show that functions can be called without arguments and they will work ! 


```python
#Initialize linear spacr
y = np.linspace(0,1, 100)
```


```python
#Call plotting style function
set_plotting_style()
plt.plot(y)
plt.show()
```


```python
#Call plotting style function 2
set_plotting_style_2()
plt.plot(y)
plt.show()
```

## Keyword arguments

A neat feature when writing functions in python is that you don't need to specify the number of arguments you'll use in a function by using `*args` and `**kwargs`. This means you can pass a variable number of arguments to a function. In brief, `*args` help you to specify arguments to send a to send a non-keyworded variable-length argument list to functions. Moreover the `**kwargs` are used to pass a keyworded, variable-length argument dictionary to a function. Let's use an example for you to see their amazing usefulness. 



```python
def multiply(*args):
    z = 1
    for num in args:
        z *= num
    print(z)
```


```python
multiply(44, 5)
multiply(10, 92.3)
multiply(2, 3, 44)
multiply(3, 5, 10, 6)
multiply(3,4 ,555, 73.4,3)
```


```python
def print_kwargs(**kwargs):
        print(kwargs)

print_kwargs(kwargs_1="Izamal", kwargs_2=4.5, kwargs_3=True)
```


```python

```

c0bd94b63cfcdebf6020e4bba30b3fb742132e49
ipynb
Jupyter Notebook
notebooks/t05-TCD-intro-to-functions.ipynb
eflobau/TCD_19
de2a9ac2f9498863b9c1a20e1e25f9b94050ffc8
MIT
2021-02-07T20:14:34.000Z
2021-02-07T20:14:34.000Z
notebooks/t05-TCD-intro-to-functions.ipynb
eflobau/TCD_19
de2a9ac2f9498863b9c1a20e1e25f9b94050ffc8
MIT
2020-01-28T22:39:39.000Z
2022-02-10T00:10:43.000Z
notebooks/t05-TCD-intro-to-functions.ipynb
manuflores/TCD_19
de2a9ac2f9498863b9c1a20e1e25f9b94050ffc8
MIT
2019-04-22T20:21:50.000Z
2019-07-24T06:27:03.000Z
Qwen/Qwen-72B
1. YES
2. YES