import numpy as np
4 Custom Functions
4.1 Introduction
Custom functions are user-defined functions created to automate specific tasks. In this section, we show how to define custom functions in Python.
\[ \DeclareMathOperator{\cov}{cov} \DeclareMathOperator{\corr}{corr} \DeclareMathOperator{\var}{var} \DeclareMathOperator{\SE}{SE} \DeclareMathOperator{\E}{E} \DeclareMathOperator{\A}{\boldsymbol{A}} \DeclareMathOperator{\x}{\boldsymbol{x}} \DeclareMathOperator{\sgn}{sgn} \DeclareMathOperator{\argmin}{argmin} \newcommand{\tr}{\text{tr}} \newcommand{\bs}{\boldsymbol} \newcommand{\mb}{\mathbb} \]
4.2 Defining functions
The following syntax can be used to declare a function in Python:
def function_name(arguments):
"""docstring"""
statementsreturn expression_list
A function is defined using the def
keyword, and its output is returned with the return
keyword. The function name, function_name
, is user-defined. The arguments
are supplied by the user and represent the inputs required to generate the result (output). Inside the function, a docstring
(enclosed in triple quotes) can be included to describe the purpose of the function, its inputs, and outputs. Although optional, the docstring is helpful for documentation and can be accessed via help(function_name)
. The statements
are the set of Python commands that form the function’s body and ultimately produce the expression_list
, which represents the function’s output.
Consider the \(L_p\) distance between two vectors \(x=(x_1,\dots,x_n)^{'}\) and \(y=(y_1,\dots,y_n)^{'}\) defined by \(d_p(x,y)=\left(\sum_{i=1}^n|x_i-y_i|^p\right)^{1/p}\). In the following example, we define the Lp_norm()
function that returns \(d_p(x,y)\).
def Lp_norm(x, y, p):
"""
Calculate the L_p distance between two vectors.
Parameters:
x (array-like): The first vector.
y (array-like): The second vector, which must be the same length as x.
p (float): The order of the norm (p > 0).
Returns:
float: The L_p distance between vectors x and y.
Raises:
ValueError: If the length of x and y are not equal, or if p is not greater than 0.
"""
if len(x) != len(y):
raise ValueError("Vectors x and y must be of the same length.")
if p <= 0:
raise ValueError("p must be greater than 0.")
= (np.sum(np.abs(x - y) ** p)) ** (1 / p)
d return d
The docstring
can be accessed using the help()
function, as shown below:
help(Lp_norm)
Help on function Lp_norm in module __main__:
Lp_norm(x, y, p)
Calculate the L_p distance between two vectors.
Parameters:
x (array-like): The first vector.
y (array-like): The second vector, which must be the same length as x.
p (float): The order of the norm (p > 0).
Returns:
float: The L_p distance between vectors x and y.
Raises:
ValueError: If the length of x and y are not equal, or if p is not greater than 0.
We use the name of the function, Lp_norm()
, to call the function. The inputs to the function are passed as arguments in the order they are defined in the function declaration. In this case, x
and y
are the vectors, and p
is the order of the norm. The function returns a single output, which is the \(L_p\) distance between the two vectors.
# Call the lp_norm function
= np.random.randn(10)
x = np.random.randn(10)
y = Lp_norm(x, y, 2) # default oder of inputs
z1
z1= Lp_norm(p=2, x=x, y=y) # changing the order of inputs
z2 z2
2.7503918685597717
2.7503918685597717
If there are multiple outputs to return, we can return these outputs in tuple form, as shown in the following example:
def L12_norm(x, y):
"""
Calculate the L1 and L2 distances between two vectors.
This function computes both the L1 distance (Manhattan distance)
and the L2 distance (Euclidean distance) between two vectors x and y.
Parameters:
x (array-like): The first vector.
y (array-like): The second vector, which must be the same length as x.
Returns:
tuple: A tuple containing:
- float: The L1 distance between vectors x and y.
- float: The L2 distance between vectors x and y.
Raises:
ValueError: If the length of x and y are not equal.
"""
if len(x) != len(y):
raise ValueError("Vectors x and y must be of the same length.")
= np.sum(np.abs(x - y)) # L1 distance
d1 = (np.sum(np.abs(x - y) ** 2)) ** (1 / 2) # L2 distance
d2 return (d1, d2)
help(L12_norm)
Help on function L12_norm in module __main__:
L12_norm(x, y)
Calculate the L1 and L2 distances between two vectors.
This function computes both the L1 distance (Manhattan distance)
and the L2 distance (Euclidean distance) between two vectors x and y.
Parameters:
x (array-like): The first vector.
y (array-like): The second vector, which must be the same length as x.
Returns:
tuple: A tuple containing:
- float: The L1 distance between vectors x and y.
- float: The L2 distance between vectors x and y.
Raises:
ValueError: If the length of x and y are not equal.
# Call the l1_l2_norm function
= np.random.randn(10)
x = np.random.randn(10)
y = L12_norm(x, y)
z
zprint("The L1 distance is ", z[0])
print("The L2 distance is ", z[1])
(11.803015755674595, 4.473714161651994)
The L1 distance is 11.803015755674595
The L2 distance is 4.473714161651994
Default values are set in the function declaration using the syntax parameter=default
. By using default values, we can call a function with fewer arguments than it is defined to accept. In the following example, the default value of p
is set to 2.
# Setting default values
def Lp_norm(x, y, p=2):
= (np.sum(np.abs(x - y) ** p)) ** (1 / p)
d return d
The default value can be overridden by passing a different value for p
when calling the function. If no value is provided, the function will use the default value of 2.
# Call the lp_norm function
= np.random.randn(10)
x = np.random.randn(10)
y # Inputs with default values can be ignored
= Lp_norm(x, y)
L2 = Lp_norm(x, y, 1)
L1 print("The L1 and L2 distances are ", (L1, L2))
The L1 and L2 distances are (7.662887260131665, 2.9283326404193204)
4.3 Anonymous functions
Python supports anonymous functions through the lambda
keyword. The syntax for a lambda function is as follows:
= lambda arguments: expression function_name
Lambda functions can accept any number of arguments, but they can only contain a single expression. Consider the following example:
= lambda x, y, p: (np.sum(np.abs(x - y) ** p)) ** (1 / p) Lp_norm_lambda
# Call the Lp_norm_lambda function
= np.random.randn(10)
x = np.random.randn(10)
y =2) Lp_norm_lambda(x, y, p
4.094891129789051