Python. Передача функции как аргумента. Структуры данных, содержащих перечень функций

Передача функции как аргумента. Структуры данных, содержащих перечень функций. Возврат функции из другой функции оператором return. Примеры


Содержание


Поиск на других ресурсах:




1. Передача функции в качестве аргумента. Общие понятия

Любая объявленная функция может быть передана в другую функция в качестве аргумента. Поскольку каждая функция является объектом, то передается ссылка на эту функцию. Функция, которая получает ссылку может по этой ссылке вызывать другую функцию соблюдая правильное задание количества и типа параметров.
В общем случае передача функции в качестве параметра выглядит следующим образом

# Функция, которая будет передана в другую функцию
def FuncArg(parameters1):
    ...

# Функция, получающая ссылку на функцию FuncArg как параметр
def Func(FuncArg, parameters2):
    ...

здесь

  • FuncArg — функция, ссылка на которую передается в другую функцию. Имя функции (FuncArg) есть ссылкой на функцию;
  • Func — имя функции, которая получает входным параметром ссылку на функцию FuncArg;
  • parameters1, parameters2 — соответственно параметры функций FuncArg() и Func().

   

2. Примеры передачи функции в качестве аргумента
2.1. Решение квадратного уравнения. Передача функции, вычисляющей дискриминант в качестве аргумента

В примере реализована функция SquareRoot(), которая возвращает корни квадратного уравнения. Функция получает 4 параметра:

  • func — имя ссылки на функцию;
  • a, b, c — коэффициенты квадратного уравнения.

В теле функции SquareRoot() осуществляется вызов функции-параметра func(). При вызове указываются 3 параметра a, b, c.
Чтобы не было ошибки, при вызове функции SquareRoot() из другого кода, нужно, чтобы имя ссылки соответствовало (ассоциировалось) функции, получающей строго 3 параметра. В противном случае, будет сгенерирована ошибка.

# Функция SquareRoot(), которая получает ссылку на некоторую функцию.
# Функция вовращает решение квадратного уравнения в виде списка.
# Если уравнение не имеет корней, функция возвращает пустой список.
def SquareRoot(func, a, b, c):
    D = func(a, b, c) # вызов функции с 3-мя параметрами
    if (D<0):
        return [] # уравнение не имеет решения
    else:
        x1 = (-b - math.sqrt(D))/(2*a)
        x2 = (-b + math.sqrt(D))/(2*a)
    return [x1, x2]

# Функция, которая вычисляет дискриминант
def Discr(a, b, c): # функция получает 3 параметра
    return b*b - 4*a*c

# Передача функции Discr() как параметра в функцию SquareRoot()
roots = SquareRoot(Discr, 2, 1, -1)
if roots != []:
    print("x1 = ", roots[0])
    print("x2 = ", roots[1])
else:
    print("The equation has no roots")

Результат выполнения программы

x1 = -1.0
x2 = 0.5

   

2.2. Пример передачи в функцию ссылки на функцию. Выполнение базовых операций над комплексными числами

В примере реализовано 5 функций:

  • AddComplex() — возвращает сумму двух комплексных чисел в виде кортежа;
  • SubComplex() — возвращает разницу двух комплексных чисел в виде кортежа;
  • MulComplex() — возвращает произведение двух комплексных чисел;
  • DivComplex() — возвращает результат деления двух комплексных чисел. В случае деления на 0 функция возвращает пустой кортеж;
  • OperationComplex() — выполняет одну из четырех операций по ссылкам на соответствующие методы.
# Операции над комплексными числами
# Суммирование
def AddComplex(x1, y1, x2, y2):
    return (x1+x2, y1+y2)

# Вычитание
def SubComplex(x1, y1, x2, y2):
    return (x1-x2, y1-y2)

# Умножение
def MulComplex(x1, y1, x2, y2):
    return ((x1*x2 - y1*y2), (x1*y2 + y1*x2))

# Деление
def DivComplex(x1, y1, x2, y2):
    t = x2*x2+y2*y2 # знаменатель
    if t==0:
        return tuple() # если деление на 0, то вернуть пустой кортеж
    else:
        re = x1*x2 + y1*y2
        im = x2*y1 - x1*y2
    return (re, im)

# Функция, которая выполняет одну из 4-х операций (функций).
# Параметры:
# - fn - ссылка на функцию, которая передается как параметр;
# - x1, y1 - вещественная и мнимая части первого комплексного числа;
# - x2, y2 - вещественная и мнимая части второго комплексного числа;
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)

# Вызов функции OperationComplex() для заданных x1, y1, x2, y2
# Ввести комплексные числа
x1 = int(input("x1 = "))
y1 = int(input("y1 = "))
x2 = int(input("x2 = "))
y2 = int(input("y2 = "))

# Реализация суммирования - передать функцию AddComplex()
resAdd = OperationComplex(AddComplex, x1, y1, x2, y2)
PrintComplex("resAdd = ", resAdd)

# Реализация вычитания - передать функцию SubComplex()
resSub = OperationComplex(SubComplex, x1, y1, x2, y2)
PrintComplex("resSub = ", resSub)

# Реализация умножения - передать функцию MulComplex()
resMul = OperationComplex(MulComplex, x1, y1, x2, y2)
PrintComplex("resMul = ", resMul)

# Деление
resDiv = OperationComplex(DivComplex, x1, y1, x2, y2)
PrintComplex("resDiv = ", resDiv)

Результат выполнения программы

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. Пример конвертирования чисел из десятичной системы счисления в двоичную и шестнадцатеричную. Передача функций конвертирования в качестве параметров.

В примере реализованы 3 функции:

  • функция Convert_10_to_2() — конвертирует строку s, представляющую целое число в десятичной системе исчисления, в соответствующую строку, представляющую число в двоичной системе исчисления;
  • функция Convert_10_to_16() — конвертирует строку s, задающую число в системе исчисления с основанием 10 в строку, задающую число в системе исчисления с основанием 16;
  • функция Convert() — получает параметром ссылку func на функцию, соответствующую функции с одним параметром типа строка. По этой ссылке вызывается функция.

В программе функции Convert_10_to_2() и Convert_10_to_16() передаются как параметры в функцию Convert() для вызова.

# Ссылка на функцию. Вызов функции по ссылке

# Функция, которая вызывает другую функцию с параметром s
def Convert(func, s):
    return func(s)

# Функция, которая конвертирует из десятичной системы исчисления в двоичную
# Параметр s - целое число в десятичной системе исчисления,
# представленное как строка
def Convert_10_to_2(s):
    res ="" # результирующая строка

    # Получить строку как число
    num = int(s)

    while num>0:
        t = num % 2 # Получить последнюю цифру (0 або 1)
        res = str(t) + res # Прибавить последнюю цифру к результирующей строке
        num = num//2 # деление на 2 нацело

    return res

# Функция, которая конвертирует число в виде строки
# из системы исчисления с овнованием 10 в систему исчисления с основанием 16
def Convert_10_to_16(s):
    res = "" # результирующая строка

    # Получить строку как целое число с основанием 10
    num = int(s)

    while num>0:
        t = num%16

        # Если t в диапазоне от 10 до 15,
        # то прибавить соответствующую букву '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

# Конвертировать число 255 в двоичную систему исчисления.
# Вызывается функция Convert() с параметром Convert_10_to_2
bin_num = Convert(Convert_10_to_2, "255")
print(bin_num)

# Конвертировать число 269 в шестнадцатеричную систему исчисления.
# Вызывается функция Convert() с параметром Convert_10_to_16
hex_num = Convert(Convert_10_to_16, "269")
print(hex_num)

Результат выполнения программы

11111111
10D

   

2.4. Пример передачи в функцию двух ссылок на функции, которые оперируют числами

В примере демонстрируется передача двух ссылок на функции в качестве параметров. Заданы две функции:

  • SumNumbers() — определяет сумму цифр числа, которое задается входным параметром;
  • MaxDigit() — определяет максимальную цифру числа, которое есть входным параметром.

С помощью функции OperationNumber() осуществляется вызов функций SumNumbers() и MaxDigit(). Функции SumNumbers() и MaxDigit() передаются в функцию OperationNumber() в качестве параметров.

# Функция, вычисляющая сумму цифр числа
def SumNumbers(n):
    summ = 0 # искомая сумма
    n2 = n
    while n>0:
        t = n%10 # выделить последнюю цифру
        summ += t
        n = n//10 # уменьшить n
    print("The sum of digits of number ", n2, " = ", summ)
    return summ

# Функция, вычисляющая максимальную цифру числа и выводящая ее на экран
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

# Функция, которая получает две ссылки на функции
def OperationNumber(n, fn1, fn2):
    fn1(n) # вызвать функцию fn1
    fn2(n) # вызвать функцию fn2

# Вычислить и вывести максимальную цифру и сумму цифр числа 2852
OperationNumber(2852, MaxDigit, SumNumbers)

   

3. Структуры данных, содержащие перечень функций

Поскольку функции являются объектами, то существует возможность создавать различные структуры данных, содержащих функции. При создании таких структур данных, каждую функцию и перечень ее параметров формируют в виде кортежа.

Например, список функций с одним параметром может быть таким

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

здесь

  • func1, func2, …, funcN – перечень имен функций или ссылок на функции;
  • param1, param2, …, paramN – перечень параметров соответственно функций func1, func2, …, funcN.

После такого описания можно вызвать функцию как элемент списка по образцу

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

здесь

  • имя LF[0][0] будет заменено именем func1;
  • имя LF[0][1] будет заменено именем param1.

   

4. Пример списка функций. Массив вызовов функции Convert_2_to_10(), которая конвертирует число из двоичной системы исчисления в десятичную

В примере формируется список ListConvert, содержащий кортежи, состоящие из имени функции Convert_2_to_10() и параметра-строки. Функция Convert_2_to_10() конвертирует число из двоичной системы исчисления в десятичную систему исчисления. Функция получает входным параметром число в виде строки и возвращает преобразованное число также в виде строки.

# Создание списка функций с параметрами для их дальнейшего вызова
import math

# Функция, конвертирующая число из двоичной системы исчисления в десятичную.
def Convert_2_to_10(s):
    # Проверка строки s на корректность
    for c in s:
        if (c!='0')and(c!='1'): return "" # выход, если недопустимые символы в строке

    num = 0 # результирующее число типа int
    power = 0 # текущая степень
    i = 0
    while i<len(s):
        bit = int(s[len(s)-i-1]) # получить один бит от конца строки
        power = int(math.pow(2, i)) # получить 2^i как целое число
        num = num + power*bit # увеличить число
        i = i+1

    # Конвертировать число num в строку
    return str(num)

# Функция, которая вызывает другую функцию с параметром s
def Convert(func, s):
    return func(s)

# Конвертировать число 10010 в десятичную систему исчисления
n = Convert(Convert_2_to_10, "10010")
print("n = ", n)

# Создать список вызовов функций 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]) # Вызов функции
Convert_2_to_10("100111")
print("n2 = ", n2)

# Обход списка
for (fn, param) in ListConvert:
    snum = fn(param) # Вызвать функцию с параметром
    print("snum = ", snum)

Результат выполнения программы

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

   

5. Возврат функции из другой функции оператором return. Пример

Функции могут создаваться и возвращаться другими функциями. В наиболее общем случае, создание и возвращение функции выглядит следующим образом:

def FuncOut(parameters1):
    ...

    # Объявление функции FuncIn() внутри функции FuncOut()
    def FuncIn(parameters2):
        # код функции FuncIn()
        ...

    # Вернуть функцию FuncIn()
    return FuncIn

После такого объявления, использование функции FuncOut() может быть, например, таким

refFn = FuncOut(parameters1)
refFn(parameters2)

Пример. В примере в функции ProcessList() реализована функция AvgList(), которая возвращает среднее арифметическое элементов списка, который есть входным параметром функции ProcessList(). Результатом работы функции ProcessList() является функция AvgList().

# Возврат функции оператором return.

# Функция, возвращающая другую функцию.
def ProcessList(L):

    # Внутри функции ProcessList() реалізована другая функция AvgList()
    def AvgList(L):
        summ = 0
        for item in L:
            summ = summ + item
        return summ/len(L)

    # Вернуть функцию AvgList(L)
    return AvgList

# Демонстрация использования функций ProcessList() и AvgList()
# Создать некоторый набор чисел
LL = [ 2, 7, 3, 4, 0, 2, 3]

# присвоить ссылке fnAvg функцию ProcessList.AvgList()
fnAvg = ProcessList(LL)

# Вызвать функцию AvgList() по ссылке
average = fnAvg(LL)

# Вывести результат
print("average = ", average)

Результат выполнения программы

average = 3.0

   


Связанные темы