Перейти до змісту

Функції вищого порядку

Ще одним принциповим положенням функційного програмування є функції вищого порядку.

Функції як об'єкти

Вже не раз згадувалось, що "в Python усе є об'єкт". І функції тут не вийняток.

>>> def f():
...     pass
...
>>> f
<function f at 0x000002877927F0D0>
>>> type(f)
<class 'function'>
>>>

Тобто функції — це об'єкти, які належать до класу function.

Об'єкт першого класу

Об'єкт називають «об'єктом першого класу», якщо:

  • його може бути збережено у змінній або інших структурах даних;
  • його може бути передано в функцію як аргумент;
  • його може бути поверненим з функції як результат;
  • його може бути створено під час виконання програми;
  • він внутрішньо самоідентифікується (не залежить від іменування).

Зауважте що термін «об'єкт» використовується тут у загальному розумінні і не обмежується об'єктами мови програмування.

В Python функції — об'єкти першого класу.

Посилання на функції

При оголошенні функції створюється об'єкт класу function, і паралельно створються змінна з іменем, вказаним після def. Пам'ятаючи, що змінні в Python — не що інше, як посилання на об'єкти, ми легко можемо посилатися на функцію за допомогою іншого імені:

>>> def original():
...     print("It work's")
...
>>> original()
It work's
>>> copy = original
>>> copy
<function original at 0x000002877927F158>
>>> copy()
It work's
>>>

Зауважте що об'єкт класу function має своє ім'я.

Давайте напишемо примітивний калькулятор який буде підтримувати усього чотири арифметичні операції. Нехай користувач вводить два операнди і операцію над ними, а програма виводить результат.

def add(a, b):
    return a + b

def sub(a, b):
    return a - b

def mul(a, b):
    return a * b

def div(a, b):
    return a / b

operators = {
    '+': add,
    '-': sub,
    '*': mul,
    '/': div,
}

n1 = float(input('Enter first operand: '))
op = input('Enter operator: ')
n2 = float(input('Enter second operand: '))

res = operators[op](n1, n2)

print('Result', res)

Функції вищого порядку

Функція вищого порядку — це така функція, яка приймає іншу функцію в якості аргумента та/або повертає іншу функцію.

>>> def f(x):
...     return x + 3
...
>>> def g(function, x):
...     return function(x) * function(x)
...
>>> g(f, 7)
100
>>>

У наведеному вище прикладі g() — функція вищого порядку.

Функції як аргументи

Для початку давайте розглянемо ще одну вбудовану функцію Python:

sorted(iterable, key=None, reverse=False)

Функція повертає список який складається з відсортованих елементів послідовності iterable.

Необов'язкові аргументи:

  • key — функція з одним параметром. Цій функції будуть передаватись елементи iterable. Функція має повертати "ключ" сортування, тобто ті значення, по яким буде відбуватись порівняння елементів iterable. За замовчуванням дорівнює None, тобто усі елементи порівнюються "напряму".
  • reverse — типу bool. Якщо True, то елементи послідовності будуть відсортовані у зворотньому порядку.

Простий приклад: маємо список символьних рядків, який треба відсортувати.

>>> l = ['John', 'jam', 'Jane', 'job']
>>> sorted(l)
['Jane', 'John', 'jam', 'job']
>>>

Отримали відсортований список рядків. Зауважте, що символьні рядки відсортовані у лексиграфічному порядку, тобто при порівнюванні рядкків між собою враховувався регістр букв (верхній чи нижній).

А тепер припустимо, що нам потрібно відсортувати список символьних рядків не враховуючи регістр останніх. Найпростіше — приводити усі символьні рядки до одного регістру перед тим як порівнювати їх між собою.

Отже функції sorted() можна передати як аргумент ще одну функцію, яка у свою чергу буде трошки "змінювати" наші символьні рядки. Визначимо останню:

>>> def to_lower(string):
...     return string.lower()
...
>>>

І тепер передаємо її у якості аргументу:

>>> sorted(l, key=to_lower)
['jam', 'Jane', 'job', 'John']
>>>

Додаткові матеріали

Back to top