Модуль 6 · Функции и модули

Справочник по Python · модуль 6 · функции и модули

Глава 6.8

6.8

Функции
высшего порядка

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

Категория
Функции
Уровень
Средний
Связанные темы
def, return, коллекции, итераторы
Зачем это знать
Передавать программе правило обработки данных

§1Что значит «высшего порядка»

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

Схемаданные и правило отдельно
общая_операция(правило, данные)
                │        └─ что обрабатывать
                └────────── как обрабатывать

§2Передача функции без вызова

Скобки вызывают функцию. Поэтому apply_twice(double, 5) передаёт саму функцию double, а внутри apply_twice она вызывается два раза.

main.pyфункция в аргументе
def double(number):
    return number * 2

def apply_twice(operation, value):
    return operation(operation(value))

print(apply_twice(double, 5))
Вывод5 → 10 → 20
20

§3Функция как результат

Внешняя функция может подготовить и вернуть внутреннюю функцию. Возвращаемое правило запоминает выбранный множитель.

main.pyсоздаём две операции
def make_multiplier(factor):
    def multiply(number):
        return number * factor
    return multiply

double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5), triple(5))
Выводразные сохранённые множители
10 15

§4map(): преобразование элементов

map(function, iterable) вызывает функцию для каждого элемента и выдаёт результаты в том же порядке.

main.pyквадрат каждого числа
def square(number):
    return number ** 2

numbers = [1, 2, 3, 4]
result = map(square, numbers)
print(list(result))
Выводчетыре результата
[1, 4, 9, 16]

Другой практический пример — преобразование строк в числа: list(map(int, ["1", "2", "3"])).

§5map() возвращает итератор

map() не создаёт готовый список. Он выдаёт значения по мере перебора и после полного чтения исчерпывается.

main.pyвторой проход пуст
def double(number):
    return number * 2

result = map(double, [1, 2, 3])
print(list(result))
print(list(result))
Выводитератор уже прочитан
[2, 4, 6]
[]

§6Несколько источников в map()

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

main.pyпопарное сложение
def add(left, right):
    return left + right

left = [1, 2, 3]
right = [10, 20, 30]
print(list(map(add, left, right)))
Выводтри суммы
[11, 22, 33]

§7filter(): отбор элементов

filter(function, iterable) сохраняет исходный элемент, если функция вернула истинное значение.

main.pyтолько чётные
def is_even(number):
    return number % 2 == 0

numbers = [1, 2, 3, 4, 5]
result = filter(is_even, numbers)
print(list(result))
Выводпроверка истинна дважды
[2, 4]
ФункцияЧто делаетДлина результата
map()заменяет каждый элемент результатом функцииобычно равна длине источника
filter()оставляет подходящие исходные элементыне больше длины источника

§8filter(None, ...)

Если вместо функции передать None, останутся только истинные элементы. Ноль, пустая строка, False и None будут удалены.

main.pyубираем ложные значения
data = [0, 1, False, 2, "", 3, None]
print(list(filter(None, data)))
Выводтолько истинные элементы
[1, 2, 3]

§9sorted() и функция key

sorted(iterable, key=function) вызывает key для каждого элемента и сравнивает полученные ключи. Сами элементы остаются в результате целиком.

main.pyсортировка слов по длине
words = ["python", "go", "java"]
result = sorted(words, key=len)
print(result)
Выводот короткого к длинному
['go', 'java', 'python']

§10map(), filter() или включение

Одинаковую задачу часто можно записать несколькими способами. Включение удобно, когда преобразование или условие короткое. map() и filter() выразительны, когда уже существует хорошо названная функция.

main.pyдва равных результата
def is_even(number):
    return number % 2 == 0

numbers = [1, 2, 3, 4]
through_filter = list(filter(is_even, numbers))
through_comp = [number for number in numbers if is_even(number)]
print(through_filter == through_comp)
Выводспособ отличается, данные нет
True

§11Частые ошибки

Что написаноЧто произойдётКак правильно
map(square(), numbers)функция вызывается без аргумента ещё до работы map()map(square, numbers)
print(map(square, numbers))выведется представление объекта map, не готовые числаprint(list(map(square, numbers)))
читать один объект map дваждыпосле первого полного прохода он исчерпансразу сохранить list(result) или создать map() заново
ожидать от filter() результатов функциифункция возвращает исходные подходящие элементыдля преобразования использовать map()
передать в map() функцию с неподходящим числом параметровTypeError во время переборасопоставить параметры функции с количеством источников

§12Проверьте себя

Почему в map(square, numbers) после square нет скобок?

Нужно передать саму функцию; вызывать её для элементов будет map().

Чем отличаются map() и filter()?

map() преобразует каждый элемент, а filter() оставляет исходные элементы, прошедшие проверку.

Что делает параметр key у sorted()?

Задаёт функцию, результат которой используется как ключ сравнения каждого элемента.

§13Шпаргалка

Преобразованиеmap(function, iterable)
Отборfilter(predicate, iterable)
Истинные элементыfilter(None, iterable)
Ключ сортировкиsorted(items, key=function)

Итог главы

Функции высшего порядка принимают или возвращают функции. map() применяет правило к каждому элементу, filter() оставляет элементы по условию, а sorted(..., key=...) вычисляет ключ сортировки. map() и filter() возвращают исчерпаемые итераторы.

Глава 6.8 · Функции высшего порядка · Справочник по PythonАвтор: Макаров Максим Николаевич