Functions and packages#

We have seen that we could define variables and do some basic operations with them. If we want to go beyond simple arithmetic we need more complex functions that can operate on variables.

Just like a regular function like \(y = f(x)\), Python functions have some definition \(f\), take an input \(x\) and give an output \(y\). There are four types of functions: built-in functions (coming with Python), functions that you define, functions from internal Python packages (no installation necessary) and functions from external packages (installation necessary).

Built-in functions#

Python comes with a series of default functions that are of general interest and often used. For example if you define a variable, you can ask for its type: is it an integer, text etc. For this you can use the type function taking a variable as input and outputting the type:

a = 3
type(a)
int

As you see, function again are called like a mathematical functio.

You own function#

To better understand the behavior of functions, we now see how we can create our own one. Imagine for example that we need a function \(f(x, a, b) = a * x + b\). For this we can use and define functions. Here’s how we can define the previous function:

def my_fun(x, a, b):
    out = a * x + b
    return out

We see a series of Python rules to define a function:

  • we use the word def to signal that we are creating a function

  • we pick a function name, here my_fun

  • we open the parenthesis and put all our variables x, a, b in there, just like when we do mathematics

  • we do some operation inside the function. Inside the function is signal with the indentation: everything that belong inside the function (there could be many more lines) is shifted by a single tab or three space to the right

  • we use the word return to tell what is the output of the function, here the variable out

We can now use this function as if we were doing mathematics: we pick a a value for the three parameters e.g. \(f(3, 2, 5)\)

my_fun(3, 2, 5)
11

If we need to use the output, we can just assign it to a new variable:

y = my_fun(3, 2, 5)
y
11

Python modules#

The mechanism of Python to enhance its capabilities are modules. Those are software packages that can be imported in a notebook or script. Python itself comes with a series of modules. Unlike the type function or the function that we defined, those modules need to be imported. For example we can import the os module that deals with files, paths etc.

import os

The import statement above says that we want to get access to the os module. Now we can access the functions from the os module via the dot notation. For example, we can ask what is the current path (where we are located):

os.getcwd()
'/Users/gw18g940/GoogleDrive/BernMIC/Trainings/DAVPy_intro/notebooks'

The output is just shown above but not “captured”. We can do that by assigning the output to a variable:

cur_path = os.getcwd()
cur_path
'/Users/gw18g940/GoogleDrive/BernMIC/Trainings/DAVPy_intro/notebooks'

As you see, in the above case there’s no input variable. In general there can be either no input, one input or multiple inputs.

Packages#

In the examples above, we either defined a function ourselves or used one generally accessible in base Python but there is a third solution: external packages. These packages are collections of functions used in a specific domain that are made available to everyone via specialized online repositories. For example we will be using in this course a package called numpy that provides essential functions and structures for scientific computing. For example if we want to compute the median of a list of numbers array_in, we can then just use the median() function of numpy and apply it to an image array_out = median(im_in). The question is now: how do we access these functions?

Importing functions#

The answer is that we have to import the functions we want to use in a given notebook from a package to be able to use them. First the package needs to be installed. One of the most popular place where to find such packages is the PyPi repository. We can install packages from there using the following command either in a terminal or directly in the notebook. For example for numpy:

numpy.median
pip install numpy
Requirement already satisfied: numpy in /Users/gw18g940/mambaforge/envs/DAVPy/lib/python3.9/site-packages (1.22.2)
Note: you may need to restart the kernel to use updated packages.

Once installed we can import the packakge in a notebook in the following way (note that the name of the package:

import numpy

The import is valid for the entire notebook, we don’t need that line in each cell.

Now that we have imported the package we can access all function that we define in it using a dot notation numpy.myfun. Most packages are organized into submodules and in that case to access functions of a submodule we use numpy.my_submodule.myfun.

For example to generate a number taken from a normal distribution we need the function normal of the random module of numpy:

numpy.random.normal()
-0.7323469427727526

Note that there are multiple ways to import packages. For example we could give another name to the package, using the as statement:

import numpy.random as rd

Now if we want to use the normal function we would write:

rd.normal()
-1.7437457642623437

We can also import only a certain submodule using:

from numpy import random

And now we write:

random.normal()
0.2692681240273183

Finally, we can import a single function like this:

from numpy.random import normal
normal()
-1.380476341973896

Variables as objects#

In the Python world, variables are not “just” variables, they are actually more complex objects. So for example our variable my_text does indeed contain the text This is my text but it contains also additional features. The way to access those features is to use the dot notation my_text.some_feature. There are two types of featues:

  • functions, called here methods, that do some computation or modify the variable itself

  • properties, that contain information about the variable

For example the object my_text has a function attached to it that allows us to put all letters to lower case:

my_text = 'This is my text'
my_text
'This is my text'
my_text.lower()
'this is my text'

If we define a complex number:

a = 3 + 5j

then we can access the property real that gives us only the real part of the number:

a.real
3.0

Note that when we use a method (function) we need to use the parenthesis, just like for regular functions, while for properties we don’t.

Getting help#

If you are not sure what a function is supposed to do or what its arguments are, you have a few choices. First you can write the function and add a question mark:

os.getcwd?
Signature: os.getcwd()
Docstring: Return a unicode string representing the current working directory.
Type:      builtin_function_or_method

You can also place your cursor inside the function parenthesis and hit Shift + Enter. A window will open with a description of the function, its arguments etc.

Exercise#

  1. Open a notebook

  2. Define a function which computes \(f(x, y) = 3 * (x + y) ^2\) and test it with a few numbers

  3. There is a native Python module called sys. Import it and get the property path of sys.

  4. Import Pandas using import pandas as pd

  5. Find help for the function pd.read_csv