Анонимные функции
Помимо обычных функций, которые мы создаём с помощью ключевого слова def, в Python существуют так называемые анонимные функции, которые не имеют имени и представляют собой небольшие однострочные функции. По-другому их называют лямбда-функциями (от англ. lambda functions) из-за их связи с лямбда-исчислением, разработанным американским логиком и математиком Алонзо Чёрчем в 1930-х годах.
В этой системе функция представляется в виде выражения, которое начинается с греческой буквы лямбда λ. Например, функция, которая удваивает число, в лямбда-исчислении записывается как λx * 2, где:
- λ – указывает на начало определения функции;
- x – аргумент функции;
- 2 * x – тело функции.
Многие языки программирования, включая Python или JavaScript, заимствовали эту концепцию для создания небольших одноразовых функций.
Создание анонимных функций
Анонимные функции создаются с помощью ключевого слова lambda:
lambda параметры: выражение
Здесь:
lambda– ключевое слово, указывающее на создание анонимной функции;параметры– список параметров, который может быть пустым;выражение– одно единственное выражение, результат которого будет возвращён функцией.
Для примера давайте создадим обычную функцию для удвоения числа:
def double(x: int) -> int:
return x * 2
Анонимная функция, выполняющая это же действие, будет выглядеть следующим образом:
double_lambda = lambda x: x * 2
Анонимная функция не имеет собственного имени, однако она является объектом, поэтому её можно присвоить переменной. В качестве параметра здесь указана одна переменная x, а в качестве выражения – умножение этого параметра на число 2. Выражение в анонимной функции автоматически возвращается, поэтому нет необходимости использовать ключевое слово return.
Если мы вызовем эти две функции для одного числа, то увидим одинаковый результат:
print(double(5))
# Вывод: 10
print(double_lambda(5))
# Вывод: 10
Другими словами, анонимная функция является просто сокращённой формой для простых функций.
Однако анонимная функция может содержать только одно выражение. То есть она не может содержать циклы, присваивания и другие конструкции, которые не являются выражениями.
Использование анонимных функций
Анонимные функции чаще всего используются в качестве аргументов для других функций, которые ожидают на вход другую функцию. Это особенно полезно при работе с функциями высшего порядка, такими как sorted(), map() и filter(), которые обрабатывают элементы коллекции на основе переданной им функции.
Сортировка словаря по ключу
Функция sorted() возвращает список независимо от типа переданного ей итерируемого объекта. Если передать ей словарь, то по умолчанию она вернёт отсортированный список его ключей. Однако метод dict.items() возвращает последовательность кортежей (ключ, значение), которую также можно отсортировать:
prices = {"Яблоки": 35, "Бананы": 48, "Лимоны": 31}
sorted_prices3 = sorted(prices.items())
print(sorted_prices3)
# Вывод: [('Бананы', 48), ('Лимоны', 31), ('Яблоки', 35)]
При этом такая последовательность сортируется по первому элементу каждого кортежа – ключу, а не по значению. Так как ключами в словаре prices являются строки, то и сортируются они в лексикографическом порядке.
Но если мы хотим изменить это поведение и сортировать словарь по значениям, то нам поможет анонимная функция, принимающая кортеж и возвращающая второе его значение, которую мы можем передать параметру key:
sorted_prices4 = sorted(prices.items(), key=lambda item: item[1])
print(sorted_prices4)
# Вывод: [('Лимоны', 31), ('Яблоки', 35), ('Бананы', 48)]
Здесь lambda item: item[1] – это анонимная функция, которая принимает кортеж item и возвращает его второй элемент, а функция sorted() использует результат этой функции для сортировки.
При необходимости отсортированный список можно передать функции dict() и преобразовать его обратно в словарь:
new_prices = dict(sorted_prices4)
print(new_prices)
# Вывод: {'Лимоны': 31, 'Яблоки': 35, 'Бананы': 48}
Фильтрация чётных чисел
Анонимные функции могут использоваться для простой фильтрации элементов в коллекции. Например, оставим в списке только чётные числа:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)
# Вывод: [2, 4, 6, 8, 10]
Здесь lambda x: x % 2 == 0 – это анонимная функция, которая возвращает True, если число чётное, и False в противном случае. Функция filter() использует это значение для включения или исключения элемента из результата.
Применение функции к каждому элементу списка
Также анонимная функция может применяться к каждому элементу коллекции с помощью функции map(). Например, увеличим каждый элемент списка в 10 раз:
numbers = [1, 2, 3, 4, 5]
multiplied_by_ten = list(map(lambda x: x * 10, numbers))
print(multiplied_by_ten)
# Вывод: [10, 20, 30, 40, 50]
Здесь анонимная функция lambda x: x * 10 применяется к каждому элементу списка numbers, а map() возвращает итератор с результатами, который преобразуется в список.
Примеры
Пример 1. Сортировка результатов экзамена
Результаты экзаменов студентов в системе представляют собой список словарей. Функция sorted() сортирует их по набранным баллам: от большего к меньшему, но если у нескольких студентов одинаковый балл, то они сортируются по фамилиям в алфавитном порядке. Для этого она принимает анонимную функцию lambda student: (-student["Балл"], student["Имя"]), которая возвращает кортеж, поэтому Python сначала сравнивает первый элемент кортежа (балл), а затем, если они равны, второй элемент (имя):
students = [
{"Имя": "Крузенштерн Иван", "Балл": 95},
{"Имя": "Лазарев Михаил", "Балл": 88},
{"Имя": "Никитин Афанасий", "Балл": 95},
{"Имя": "Дежнёв Семён", "Балл": 75},
{"Имя": "Головнин Василий", "Балл": 88},
]
# Сортировка по баллам (по убыванию), затем по имени (по алфавиту)
sorted_students = sorted(students, key=lambda student: (-student["Балл"], student["Имя"]))
for student in sorted_students:
print(f"- {student['Имя']}: {student['Балл']} баллов")
Баллы сортируются по убыванию, так как перед значением student["Балл"] указан знак минус (-). Такой способ изменения направления сортировки работает только для чисел.
Вывод:
- Крузенштерн Иван: 95 баллов
- Никитин Афанасий: 95 баллов
- Головнин Василий: 88 баллов
- Лазарев Михаил: 88 баллов
- Дежнёв Семён: 75 баллов
Пример 2. Расчёт стоимости товара с учётом НДС
Конечная стоимость товара обычно включает в себя НДС (налог на добавленную стоимость). Цены товаров хранятся в списке, а по общему правилу НДС исчисляется по ставке 20 %, поэтому к каждому элементу списка нужно применить одну и ту же формулу с помощью функции map() и анонимной функции lambda price: price * 1.2, которая увеличивает цену price на 20 %:
prices = [1000, 2500, 500, 1200]
# Рассчитываем цены с налогом
prices_with_tax = list(map(lambda price: price * 1.2, prices))
print("Исходные цены:", prices)
print("Цены с учётом НДС:", prices_with_tax)
Вывод:
Исходные цены: [1000, 2500, 500, 1200]
Цены с учётом НДС: [1200.0, 3000.0, 600.0, 1440.0]
Пример 3. Фильтрация адресов электронной почты
Перед рассылкой система (весьма упрощённо) проверяет список всех почтовых адресов и c помощью функции filter() оставляет в них только те, которые содержат символы "@" и "." (точка). Для этого она принимает анонимную функцию lambda email: "@" in email and "." in email, которая возвращает True, если нужные символы содержатся в строке email и False в противном случае:
emails = [
"iron_man@example.ru",
"no-data",
"None",
"invincible_thor@domain.net",
"cap=am@",
"not_hulk@test"
]
# Фильтруем список, оставляя только валидные адреса
valid_emails = filter(lambda email: "@" in email and "." in email, emails)
print("Исходный список почтовых адресов:", *emails)
print("Проверенные адреса:", *valid_emails)
Вывод:
Исходный список почтовых адресов: iron_man@example.ru no-data None invin-cible_thor@domain.net cap=am@ not_hulk@test
Проверенные адреса: iron_man@example.ru invincible_thor@domain.net
Итоги
- Конструкция
lambda параметры: выражениесоздаёт анонимную функцию – небольшую однострочную функцию без имени. - Анонимные функции чаще всего используются в качестве аргументов для других функций, которые ожидают на вход другую функцию. Например,
sorted(),filter()иmap().
Задания для самопроверки
1. Что такое анонимная функция? Как она создаётся?
Анонимная функция – это небольшая однострочная функция без имени. Она создаётся с помощью ключевого слова lambda.
2. Что будет выведено на экран в результате выполнения следующего кода? Объясните свой ответ.
my_lambda_function = lambda a, b: a + b
print(my_lambda_function(5, 10))
Будет выведено число 15, так как анонимная функция принимает два числа и возвращает результат их сложения.
3. Напишите анонимную функцию, которая принимает три числа и возвращает их произведение. Присвойте эту функцию переменной product_lambda и вызовите её с тремя любыми числами.
product_lambda = lambda x, y, z: x * y * z
result = product_lambda(2, 5, 4)
print(result)
# Вывод: 40
4. Дан список кортежей students = [("Менделеев Иван", 4.5), ("Кюри Мария", 5.0), ("Кюри Пьер", 3.8)], где каждый кортеж содержит имя школьника и его средний балл. Используйте анонимную функцию и функцию sorted(), и отсортируйте список students по оценкам в порядке убывания (от самой высокой к самой низкой). Отсортированный список выведите на экран.
students = [
("Менделеев Иван", 4.5),
("Кюри Мария", 5.0),
("Кюри Пьер", 3.8)
]
sorted_students = sorted(students, key=lambda student: student[1], re-verse=True
)
print(sorted_students)
# Вывод: [('Кюри Мария', 5.0), ('Менделеев Иван', 4.5), ('Кюри Пьер', 3.8)]
5. Дан список numbers = [1, 2, 3, 4, 5]. Используйте анонимную функцию и функцию map(), и увеличьте каждое число из списка numbers на 10. Преобразуйте полученный итератор в список и выведите его на экран.
numbers = [1, 2, 3, 4, 5]
result = list(map(lambda x: x + 10, numbers))
print(result)
# Вывод: [11, 12, 13, 14, 15]
6. Дан список zoo = ["слон", "жираф", "крокодил", "зебра", "коала"]. Используйте анонимную функцию и функцию filter(), и создайте из списка zoo новый список, содержащий только слова, содержащие символ "к". Преобразуйте полученный итератор в список и выведите его на экран.
zoo = ["слон", "жираф", "крокодил", "зебра", "коала"]
result = list(filter(lambda word: "к" in word, zoo))
print(result)
# Вывод: ['крокодил', 'коала']
0 комментариев