Справочник по Python · модуль 6 · функции и модули
Глава 6.8
Функции
высшего порядка
Функцию можно передать другой функции как обычное значение. Благодаря этому одна общая операция получает разное поведение: преобразует, отбирает или сортирует элементы по переданному правилу.
- Категория
- Функции
- Уровень
- Средний
- Связанные темы
- def, return, коллекции, итераторы
- Зачем это знать
- Передавать программе правило обработки данных
§1Что значит «высшего порядка»
Функция высшего порядка принимает другую функцию как аргумент или возвращает функцию как результат. Переданная функция описывает не готовое значение, а правило вычисления.
общая_операция(правило, данные)
│ └─ что обрабатывать
└────────── как обрабатывать§2Передача функции без вызова
Скобки вызывают функцию. Поэтому apply_twice(double, 5) передаёт саму функцию double, а внутри apply_twice она вызывается два раза.
def double(number): return number * 2 def apply_twice(operation, value): return operation(operation(value)) print(apply_twice(double, 5))
20
§3Функция как результат
Внешняя функция может подготовить и вернуть внутреннюю функцию. Возвращаемое правило запоминает выбранный множитель.
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) вызывает функцию для каждого элемента и выдаёт результаты в том же порядке.
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() не создаёт готовый список. Он выдаёт значения по мере перебора и после полного чтения исчерпывается.
def double(number): return number * 2 result = map(double, [1, 2, 3]) print(list(result)) print(list(result))
[2, 4, 6] []
§6Несколько источников в map()
Если передать несколько итерируемых объектов, функция получит по одному аргументу из каждого. Перебор закончится вместе с самым коротким источником.
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) сохраняет исходный элемент, если функция вернула истинное значение.
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 будут удалены.
data = [0, 1, False, 2, "", 3, None] print(list(filter(None, data)))
[1, 2, 3]
§9sorted() и функция key
sorted(iterable, key=function) вызывает key для каждого элемента и сравнивает полученные ключи. Сами элементы остаются в результате целиком.
words = ["python", "go", "java"] result = sorted(words, key=len) print(result)
['go', 'java', 'python']
§10map(), filter() или включение
Одинаковую задачу часто можно записать несколькими способами. Включение удобно, когда преобразование или условие короткое. map() и filter() выразительны, когда уже существует хорошо названная функция.
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() возвращают исчерпаемые итераторы.