Функции как значения
Представьте, что вы отдаёте помощнику стопку карточек со словами и просите их разложить. Сортировать он умеет, но не знает, по какому правилу. Тогда вы даёте ему записку: «сравнивай слова по длине». В Python такая записка — это функция, которую передают другой функции.
Функция sorted упорядочивает строки по алфавиту. Чтобы отсортировать слова по длине, ей нужно сообщить, что сравнивать. Для этого sorted передают другую функцию — в именованном аргументе key:
words = ["banana", "fig", "apple", "kiwi"]
print(sorted(words)) # ['apple', 'banana', 'fig', 'kiwi']
print(sorted(words, key=len)) # ['fig', 'kiwi', 'apple', 'banana']Давайте разберём пример по строкам:
sorted(words)сравнивает сами строки, буква за буквой, и раскладывает их по алфавиту.sorted(words, key=len)получает запискуlenи вызывает её для каждого слова:6,3,5,4.- Сортировка идёт по этим числам, а в результат попадают сами слова, от
figдоbanana.
Как вы уже знаете, так же key работает у min и max.
Функция — это значение
Имя функции без скобок — это сама функция, а со скобками — её вызов:
len— функция, записка с правилом;len("fig")— результат вызова, число3.
Функцию, как число или строку, можно присвоить переменной или передать аргументом. С аргументом key функция sorted вызывает len по одному разу для каждого слова и сравнивает результаты, а не сами слова.
Передать можно и свою функцию. Функцию, которая принимает другую функцию или возвращает её, называют функцией высшего порядка: sorted с key — одна из них.
def last_letter(word):
return word[-1]
words = ["banana", "fig", "apple", "kiwi"]
check = last_letter
print(check("fig")) # g
print(sorted(words, key=last_letter)) # ['banana', 'apple', 'fig', 'kiwi']Разберём по шагам:
check = last_letterне вызывает функцию, а даёт ей второе имя. Переменнаяcheckуказывает на ту же функцию.check("fig")вызывается так же, какlast_letter("fig"), и возвращаетg.sorted(words, key=last_letter)сортирует слова по последней букве:a,e,g,i.
Здесь аналогия с запиской перестаёт работать. Записку читают один раз, а функцию sorted вызывает заново для каждого элемента. Каждый раз она получает один элемент и возвращает его ключ.
lambda
Ради одного key заводить отдельный def долго. Лямбда-функция — функция без имени, записанная в одно выражение: lambda word: word[-1] делает то же, что last_letter. Запись состоит из трёх частей:
- слово
lambda; - параметры перед двоеточием;
- выражение после двоеточия — его значение функция возвращает, без слова
return.
scores = [("max", 3), ("lee", 5), ("kim", 3)]
by_score = sorted(scores, key=lambda s: s[1])
print(by_score) # [('max', 3), ('kim', 3), ('lee', 5)]Ключ здесь — второй элемент кортежа, число очков. Ключи max и kim равны, и sorted сохранил исходный порядок: max стоял раньше, хотя по алфавиту kim идёт первым.
Сортировка в Python устойчивая: элементы с равными ключами сохраняют порядок, в котором стояли. Так же сортирует метод sort с аргументом key. Об устойчивости сортировки часто спрашивают на собеседовании, обычно на примере вроде этого.
map и filter
Встроенные map и filter тоже принимают функцию первым аргументом. Как генераторное выражение, они выдают значения по одному, поэтому результат оборачивают в list.
map
map вызывает функцию для каждого элемента и выдаёт её результаты. list(map(len, words)) даёт [6, 3, 5, 4], длину каждого слова.
filter
filter оставляет элементы, для которых функция вернула истинное значение. list(filter(lambda w: len(w) > 4, words)) даёт ['banana', 'apple'].
Чаще вместо обеих функций пишут включение, потому что оно читается проще. Те же результаты дают [len(w) for w in words] и [w for w in words if len(w) > 4].
Частая ошибка
В key передали вызов функции вместо самой функции:
words = ["banana", "fig", "apple", "kiwi"]
print(sorted(words, key=len())) # ✗TypeError: len() takes exactly one argument (0 given)Скобки вызывают len сразу, ещё до сортировки, и без аргумента. Даже с аргументом в key попало бы число, а не функция. Пишите имя без скобок: key=len.
Главное
- Имя функции без скобок — сама функция: её можно присвоить переменной или передать аргументом.
sorted,minиmaxвызывают функцию изkeyдля каждого элемента и сравнивают её результаты.lambda x: выражение— короткая функция без имени, которая возвращает значение выражения.- Сортировка устойчивая: элементы с равными ключами сохраняют исходный порядок.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.