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

 


Зв’язані теми