Functions
Two patterns often emerge with more complex questions: on the one hand, the same functionality is required in several places in the programme code (e.g. a scalar product) and on the other hand, the code becomes long and therefore confusing. Both problems can be solved with functions. Functions are almost analogous to mathematical functions. A function is a block of code that can be called with a set of arguments. This means that the same function can be called several times by different code segments (and other functions).
def print_largest(a, b):
if a > b:
print(a)
else:
print(b)
print_largest(1, 2) # 2`
Functions can also return values:
def add(a, b):
return a + b
add(1, 2) # 3
This also supports maintainability: if a logic is faulty, only this one point needs to be adapted when using functions, instead of every occurrence in a potentially large code base. In addition, the function reduces mental complexity: instead of understanding the entire code, it is sufficient to understand the function.
The difference to a mathematical function is that a function in Python can also have side effects, such as outputting something to the screen or writing a file. Functions that have no side effects but only perform calculations are called pure functions, which will be relevant later in the context of JAX.
Linking and calls
Functions can be linked by using nested expressions:
def add(a, b):
return a + b
add(add(1, 2), 3) # 6
A meaningful unit for a function is either of a logical nature (the function solves a self-contained problem) or of a practical nature (the function solves a frequently occurring sub-problem). An example is:
def add(a, b):
return a + b
def list_sum(list_to_sum):
total = 0
for element in list_to_sum:
total = add(total, element)
return total
Implicit tuples and automatic unpacking
If a function is to return more than one value, several comma-separated values can be passed to the return
statement. These are then implicitly converted into a tuple:
def min_max(list_to_analyze):
min_value = list_to_analyze[0]
max_value = list_to_analyze[0]
for element in list_to_analyze:
if element < min_value:
min_value = element
if element > max_value:
max_value = element
return min_value, max_value
min_max([1, 2, 3, 4, 5]) # (1, 5)
The tuple can then also be unpacked automatically:
min_value, max_value = min_max([1, 2, 3, 4, 5])
Functions as variables
Functions can be treated and passed on like variables. This can lead to elegant programme structures:
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def apply_operation(operation, a, b):
return operation(a, b)
apply_operation(add, 1, 2) # 3
apply_operation(subtract, 1, 2) # -1