Python. Passing a function as an argument. Data structures containing a list of functions

Passing a function as an argument. Data structures containing a list of functions. Returning a function from another function using the return statement. Examples


Contents


Search other resources:




1. Passing a function as an argument. General concepts

Any declared function can be passed to another function as an argument. Since every function is an object, a reference to that function is passed. A function that receives a reference can call another function using this reference, observing the correct setting of the number and type of parameters.

In general, passing a function as a parameter looks like this

# A function that will be passed to another function
def FuncArg(parameters1):
    ...

# A function that receives a reference to the FuncArg function as a parameter
def Func(FuncArg, parameters2):
    ...

here

  • FuncArg is a function, a reference to which is passed to another function. The function name (FuncArg) is a reference to the function;
  • Func – the name of the function that receives a reference to the FuncArg function as an input parameter;
  • parameters1, parameters2 – parameters of FuncArg() and Func() functions, respectively.

 

2. Examples of passing a function as an argument
2.1. Solving a quadratic equation. Passing a function that calculates the discriminant as an argument

The example implements the SquareRoot() function that returns the roots of a quadratic equation. The function receives 4 parameters:

  • func – the name of the reference to the function;
  • a, b, c – coefficients of the quadratic equation.

In the body of the SquareRoot() function, the function-parameter func() is called. When calling, 3 parameters a, b, c are specified.

To avoid an error, when calling the SquareRoot() function from other code, it is necessary that the reference name match (associate) a function that receives strictly 3 parameters. Otherwise, an error will be generated.

# The SquareRoot() function that receives a reference to some function.
# The function returns the solution of a quadratic equation as a list.
# If the equation has no roots, the function returns an empty list.
def SquareRoot(func, a, b, c):
    D = func(a, b, c) # function call with 3 parameters
    if (D<0):
        return [] # the equation has no solution
    else:
        x1 = (-b - math.sqrt(D))/(2*a)
        x2 = (-b + math.sqrt(D))/(2*a)
    return [x1, x2]

# Function that calculates the discriminant
def Discr(a, b, c): # function receives 3 parameters
    return b*b - 4*a*c

# Passing the Discr() function as a parameter to the Square Root() function
roots = SquareRoot(Discr, 2, 1, -1)
if roots != []:
    print("x1 = ", roots[0])
    print("x2 = ", roots[1])
else:
    print("The equation has no roots")

The result of the program

x1 = -1.0
x2 = 0.5

 

2.2. An example of passing a function reference to a function. Performing basic operations on complex numbers

The example implements 5 functions:

  • AddComplex() – returns the sum of two complex numbers as a tuple;
  • SubComplex() – returns the difference of two complex numbers as a tuple;
  • MulComplex() – returns the multiplication of two complex numbers;
  • DivComplex() – returns the result of dividing two complex numbers. If divided by 0, the function returns an empty tuple;
  • OperationComplex() – performs one of four operations on references to the corresponding methods.

 

# Operations on complex numbers
# Addition
def AddComplex(x1, y1, x2, y2):
    return (x1+x2, y1+y2)

# Subtraction
def SubComplex(x1, y1, x2, y2):
    return (x1-x2, y1-y2)

# Multiplication
def MulComplex(x1, y1, x2, y2):
    return ((x1*x2 - y1*y2), (x1*y2 + y1*x2))

# Division
def DivComplex(x1, y1, x2, y2):
    t = x2*x2+y2*y2 # denominator
    if t==0:
        return tuple() # if division by 0, then return an empty tuple
    else:
        re = x1*x2 + y1*y2
        im = x2*y1 - x1*y2
        return (re, im)

# A function that performs one of 4 operations (functions).
# Parameters:
# - fn - a reference to a function that is passed as a parameter;
# - x1, y1 - real and imaginary parts of the first complex number;
# - x2, y2 - real and imaginary parts of the second complex number;
def OperationComplex(fn, x1, y1, x2, y2):
    return fn(x1, y1, x2, y2)

def PrintComplex(text, cm):
    s = text + str(cm[0])
    if cm[1]>=0:
        s = s + "+"
    s = s + str(cm[1]) + "*j"
    print(s)

# Calling the OperationComplex() function for the given x1, y1, x2, y2
# Input complex numbers
x1 = int(input("x1 = "))
y1 = int(input("y1 = "))
x2 = int(input("x2 = "))
y2 = int(input("y2 = "))

# Summation implementation - pass the AddComplex() function
resAdd = OperationComplex(AddComplex, x1, y1, x2, y2)
PrintComplex("resAdd = ", resAdd)

# Subtraction implementation - pass the SubComplex() function
resSub = OperationComplex(SubComplex, x1, y1, x2, y2)
PrintComplex("resSub = ", resSub)

# Multiplication implementation - pass MulComplex() function
resMul = OperationComplex(MulComplex, x1, y1, x2, y2)
PrintComplex("resMul = ", resMul)

# Division
resDiv = OperationComplex(DivComplex, x1, y1, x2, y2)
PrintComplex("resDiv = ", resDiv)

The result of the program

x1 = 5
y1 = 1
x2 = 4
y2 = 9
resAdd = 9+10*j
resSub = 1-8*j
resMul = 11+49*j
resDiv = 29-41*j

 

2.3. An example of converting numbers from decimal to binary and hexadecimal. Passing conversion functions as parameters

The example implements 3 functions:

  • function Convert_10_to_2() – converts the string s, representing an integer in decimal notation, into the corresponding string representing a number in binary notation;
  • function Convert_10_to_16() – converts the string s, which specifies a number in the base 10 number system, into a string that specifies the number in the base 16 number system;
  • function Convert() – receives as a parameter the reference func to the function corresponding to the function with one parameter of the string type. The function is called from this reference.

In the program, the Convert_10_to_2() and Convert_10_to_16() functions are passed as parameters to the Convert() function to be called.

# Reference to the function. Calling a function by reference

# A function that calls another function with parameter s
def Convert(func, s):
    return func(s)

# Function that converts from decimal to binary
# S is a decimal integer represented as a string
def Convert_10_to_2(s):
    res = "" # resulting string

    # Get string as number
    num = int(s)

    while num>0:
        t = num % 2 # Get the last digit (0 or 1)
        res = str(t) + res # Append the last digit to the resulting string
        num = num//2 # division by 2

    return res

# A function that converts a number as a string from base 10 to base 16
def Convert_10_to_16(s):
    res = "" # the resulting string

    # Get string as a base 10 integer
    num = int(s)

    while num>0:
        t = num%16

        # If t is in the range from 10 to 15,
        # then add the corresponding letter 'A', 'B', 'C', 'D', 'E', 'F'
    if t>=10:
        res = chr(ord('A')+t-10) + res
    else:
        res = str(t)+res
        num = num//16

    return res

# Convert number 255 to binary notation.
# The Convert() function is called with the Convert_10_to_2 parameter
bin_num = Convert(Convert_10_to_2, "255")
print(bin_num)

# Convert number 269 to hexadecimal notation.
# The Convert() function is called with the Convert_10_to_16 parameter
hex_num = Convert(Convert_10_to_16, "269")
print(hex_num)

The result of the program

11111111
10D

 

2.4. An example of passing into a function two references to functions

The example demonstrates passing two function references as parameters. Two functions are define:

  • SumNumbers() – determines the sum of the digits of the number that is specified by the input parameter;
  • MaxDigit() – defines the maximum digit of the number that is the input parameter.

The OperationNumber() function calls the SumNumbers() and MaxDigit() functions. The SumNumbers() and MaxDigit() functions are passed to the OperationNumber() function as parameters.

# Function that calculates the sum of the digits of a number
def SumNumbers(n):
    summ = 0 # the resulting sum
    n2 = n
    while n>0:
        t = n%10 # highlight the last digit
        summ += t
        n = n//10 # decrease n

    print("The sum of digits of number ", n2, " = ", summ)
    return summ

# A function that calculates the maximum digit of a number and displays it on the screen
def MaxDigit(n):
    maxD = 0
    n2 = n
    while n>0:
        t = n%10
        if t>maxD:
            maxD = t
        n = n//10
    print("Max digit of number ", n2, " = ", maxD)
    return maxD

# A function that receives two function references
def OperationNumber(n, fn1, fn2):
    fn1(n) # invoke function fn1
    fn2(n) # invoke function fn2

# Calculate and display the maximum digit and the sum of digits of the number 2852
OperationNumber(2852, MaxDigit, SumNumbers)

 

3. Data structures containing a list of functions

Since functions are objects, it is possible to create various data structures containing functions. When creating such data structures, each function and a list of its parameters are formed in the form of a tuple.

For example, a list of functions with one parameter could be like this

LF = [ (func1, param1), (func2, param2), ..., (funcN, paramN) ]

here

  • func1, func2, …, funcN – list of function names or function references;
  • param1, param2, …, paramN – the list of parameters, respectively, functions func1, func2, …, funcN.

After such a description, you can call the function as a list item by the pattern

LF[0][0](LF[0][1]) # вызов func1(param1)

here

  • the name LF[0][0] will be replaced by the name func1;
  • the name LF[0][1] will be replaced with the name param1.

 

4. An example of a list of functions. An array of calls to the Convert_2_to_10() function, which converts a number from binary to decimal

The example forms a ListConvert list containing tuples consisting of the name of the Convert_2_to_10() function and a string parameter. The Convert_2_to_10() function converts a number from binary to decimal. The function receives as an input parameter a number as a string and returns the converted number also as a string.

# Creation of a list of functions with parameters for their further call
import math

# A function that converts a number from binary to decimal
def Convert_2_to_10(s):
    # Checking string s for correctness
    for c in s:
        if (c!='0')and(c!='1'): return "" # exit if invalid characters in string

    num = 0 # the resulting number of type int
    power = 0 # the current power of the number
    i = 0
    while i<len(s):
        bit = int(s[len(s)-i-1]) # get one bit from the end of the string
        power = int(math.pow(2, i)) # get 2^i as integer
        num = num + power*bit # increase number
        i = i+1

    # Convert num to string
    return str(num)

# A function that calls another function with parameter s
def Convert(func, s):
    return func(s)

# Convert 10010 to decimal
n = Convert(Convert_2_to_10, "10010")
print("n = ", n)

# Create a list of function calls Convert_2_to_10()
ListConvert = [ (Convert_2_to_10, "100111"),
                (Convert_2_to_10, "1111"),
                (Convert_2_to_10, "10001") ]
n2 = ListConvert[0][0](ListConvert[0][1]) # Invoke the function
Convert_2_to_10("100111")
print("n2 = ", n2)

# Bypassing list
for (fn, param) in ListConvert:
    snum = fn(param) # Invoke function with parameter
    print("snum = ", snum)

The result of the program

n = 18
n2 = 39
snum = 39
snum = 15
snum = 17

 

5. Returning a function from another function with a return statement. Example

Functions can be created and returned by other functions. In the most general case, creating and returning a function looks like this:

def FuncOut(parameters1):
    ...

    # The FuncIn() function declaration inside FuncOut() function
    def FuncIn(parameters2):
        # function code FuncIn()
        ...

    # Return FuncIn() function
    return FuncIn

After such a declaration, the use of the FuncOut() function can be, for example, like this

refFn = FuncOut(parameters1)
refFn(parameters2)

Example.

In the example in AvgList() function is implemented ProcessList() function which returns the average of the list items. The list is the input parameter of the function ProcessList(). The result of the ProcessList() function is the AvgList() function.

# Returning a function with a return statement.

# A function that returns another function.
def ProcessList(L):

    # Inside the ProcessList() function, another function AvgList() is implemented
    def AvgList(L):
        summ = 0
        for item in L:
            summ = summ + item
        return summ/len(L)

    # Return the AvgList(L) function
    return AvgList

# Demonstration of using the ProcessList() and AvgList() functions
# Create some set of numbers
LL = [ 2, 7, 3, 4, 0, 2, 3]

# assign the fnAvg referenct the ProcessList.AvgList() function
fnAvg = ProcessList(LL)

# Invoke AvgList() by reference
average = fnAvg(LL)

# Print the result
print("average = ", average)

The result of the program

average = 3.0

 


Related topics