# Docstrings

In session 2 we discussed how to write readable code, and insodoing touched on the use of comments to explain a piece of code's functionality.

We can extend this idea of **readability** to **functions** by using **docstrings** - a large block comment at the start of a function which describes what the function does, what its inputs are, and what its outputs are.

To use an example, consider the function below which calculates the kinetic energy of a particle as

$$
E_\mathrm{K} = \frac{1}{2} mv^2 
$$

```python
def kinetic_energy(m, v, verbose=False):
    ke = (1 / 2) * m * v ** 2
    if verbose:
        print(f'Kinetic energy = {ke:.2f} J')
    return ke
```

The purpose of this function might seem fairly obvious, but its good practice to write a docstring for **all functions**. We can add a docstring using triple quotes

```python
def kinetic_energy(m, v, verbose=False):
    '''
    Calculate the kinetic energy as 1/2mv^2.

    Arguments
    ---------
    m: float
        The mass of the particle in kg
    v: float
        The velocity of the particle in m/s
    verbose: bool, default False
        If True, print the calculated kinetic energy.

    Returns
    -------
    float
        The kinetic energy of the particle in Joules.
    '''
    ke = (1 / 2) * m * v ** 2
    if verbose:
        print(f'Kinetic energy = {ke:.2f} J')
    return ke
```

We can split this into several sections.

1. A description of the function's purpose - a general summary.

2. The input arguments - specifying their name, type, and meaning. We can also specify default values for optional arguments.

3. The return values - its type and meaning. Notice that as users we don't care about the name of the return variable since the name is only important within the function's **local scope**.

We've chosen a specific style for writing docstrings based on the [Numpy style](https://numpydoc.readthedocs.io/en/latest/format.html) and you should keep to this style in this course.

We can access the docstring for a given function using the `__doc__` attribute, e.g.

```python
print(kinetic_energy.__doc__)
```
```
    Calculate the kinetic energy as 1/2mv^2.

    Arguments
    ---------
    m: float
        The mass of the particle in kg
    v: float
        The velocity of the particle in m/s
    verbose: bool, default False
        If True, print the calculated kinetic energy.

    Returns
    -------
    float
        The kinetic energy of the particle in Joules.
```

This is also possible for built-in functions like `len`

```python
print(len.__doc__)
```
```
Return the number of items in a container.
```

::: {.callout-warning}
You should write a docstring for **every function**, and your docstring should always match what the function **actually** does, requires as input, and gives as output.
:::
