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

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!")

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 [ ]:
# your solution here