Functions help to avoid **code repitition** and to build libraries.

The syntax of a Python function is:

```
def func(arguments):
""" The docstring appears in help messages"""
# execute function commands
return value(s)
```

**Notes:**

- Note the colon after the function definition!
- The function code is within an idented block!
- Get into the habbit to
*always*write docstrings! I will explain more about it when we talk about modules. - A function can have an arbitrary amount of arguments and also
*default arguments*. - A function can have an arbitrary amount of return values!
- As usual for Python variables, function arguments do not have information on the type!
- All the parameters and variables that are defined in a function are local to a function, meaning that these variables cannot be
*seen*by code outside of the function (functions have an own, local*namespace*). Note also that the scope of a variable within a function is from the point it is created (either in the parameter list or in the body via an assignment operation) to the end of the function. - A function that returns
*no value*(a procedure) implicitely returns the special value**None**

```
In [ ]:
```import numpy
# a classical mathematical function
def gauss(x):
"""
Calculates the value of a Gauss function with mu = 0 and sigma = 1.0
input: A number number x (float or int) at which to evaluate
the function
return: The calculated gauss value at x
"""
return (1.0 / numpy.sqrt(2.0 * numpy.pi)) * numpy.exp(-x**2 / 2.0)
x = 1.0
print(numpy.tan(x), gauss(x))

```
In [ ]:
```import numpy
# a fucntion with default arguments:
def gauss_mu_sigma(x, mu=0.0, sigma=1.0):
""" Calculates the value of a Gauss at an input
value x
input(s):
- The value at which to evaluate the Gauss
(required argument)
- Tne mean mu of the distribution
(optional argument)
- The width sigma of the distribution
(optional argument)
return:
- The calculated gauss function value
"""
factor = (1.0 / numpy.sqrt(2.0 * sigma * numpy.pi))
expon = numpy.exp(-(x - mu)**2 / (2.0 * sigma**2))
return factor * expon
# implicit mu = 0.0, sigma = 1.0
print(gauss_mu_sigma(1.0))
# explicit mu and sigma
print(gauss_mu_sigma(1.0, mu = 1.0, sigma = 2.0))
# implicit sigma = 1.0
print(gauss_mu_sigma(1.0, mu = 1.0))
# implicit mu = 0.0
print(gauss_mu_sigma(1.0, sigma = 2.0))

```
In [ ]:
```import numpy
# a function with two input and two output values
def xy_to_polar(x, y):
""" Here is the docstring for xy_polar """
# transform two-dimensional cartesian coordinates
r = numpy.sqrt(x**2 + y**2)
theta = numpy.arctan2(y, x)
return r, theta
radius, angle = xy_to_polar(1.0, 1.0)
# note that the angle is given in radians!
print(radius, angle)

```
In [ ]:
```import colorama # module to enable coloured output in print statements
# a function with 'no' return value
def print_error(str):
""" Docstring for function print_error """
print(colorama.Fore.RED + "Error: " + str + colorama.Style.RESET_ALL)
# The following explicit return None can be omitted.
return None
print_error("File not found!")

```
In [ ]:
```def p(x): # p(x) prints its result 'and' returns None!
print(2 * x)
def r(x): # r(x) returns its result!
return 2 * x
# When interactively calling the two functions, they both seem to
# behave the same way:
p(10)
r(10)
# The results are however different, when 'assiging' the functions
# results to variables:
p_result = p(10)
r_result = r(10)
print(p_result, r_result)
# Note that you need to 'return' the result of a function if you
# want to use it later (assign it to a variable)! If in doubt, then
# return the result!

Try to answer the following question without executing the codes:

What is the output of the

`print`

-statements in the follwing code:`def triple(x): x = x * 3 print(x) x = 5 print(triple(x))`

What did the programmer of the function probably intend to do?

- What is the output of the following code:
`a = print(5) print(a)`

```
In [ ]:
``````
# you can try them here now!
```

Write the inverse function to

`xy_to_polar`

. Its name should be`polar_to_xy`

and it should accept polar coordinates $(r, \theta)$ of a point in the two-dimensional plane. The function should return the corresponding $x$ and $y$ coordinates.Try the function call

`polar_to_xy(*xy_to_polar(1.0, 1.5))`

and explain what it does.**Hint:**$x = r \cos(\theta)$ and $y = r \sin(\theta)$. Note that the angle $\theta$ has to be provided in radians!

```
In [ ]:
``````
# your solution here
```