# Functions in Python

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

## Some simple examples



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

# note that the angle is given in radians!




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



## printing vs. returning function results

Many students have difficulties to understand the difference between printing the result of a function and returning the result of a function. The confusion arises because, in some sitouations, they behave the same way



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!



## Exercises:

• 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 [ ]: