Лямбда-функции в Python

Допустим, есть список студентов, и нужно отсортировать его по оценке. Функция sorted() это умеет, но ей надо объяснить, по какому полю сравнивать — передать маленькую функцию «достань оценку». Заводить ради одной строки полноценную функцию через def, придумывать ей имя и выносить отдельным блоком — громоздко.

Для таких случаев есть лямбда-функции: крошечная функция прямо там, где она нужна, без имени и без def.

Лямбда-функция — это безымянная функция из одного выражения: она принимает аргументы и возвращает результат этого выражения.

Отсюда три её черты:

  • Безымянная — её не объявляют через def с именем, а пишут по месту
  • Из одного выражения — тело это одна строка, результат которой возвращается
  • Это функция — принимает аргументы и возвращает значение

Синтаксис лямбда-функции

Python 3.13
lambda аргументы: выражение

Где:

  • lambda — это ключевое слово, которое сообщает Python, что мы создаём лямбда-функцию
  • аргументы — это входные параметры (могут быть от 0 до нескольких, разделенных запятыми)
  • выражение — это одно выражение, результат которого будет возвращен

Сравнение с обычными функциями

Сравним обычную функцию и лямбда-функцию, которые делают одно и то же:

Python 3.13
# Обычная функция
def square(x):
    return x * x

# Эквивалентная лямбда-функция
square_lambda = lambda x: x * x

# Используем обе функции
print(square(5))
25
print(square_lambda(5))
25
# Функция с несколькими аргументами
def power(base, exponent):
    return base ** exponent

# Эквивалентная лямбда-функция
power_lambda = lambda base, exponent: base ** exponent

print(power(2, 3))
8
print(power_lambda(2, 3))
8

Лямбда-функции компактнее, но для сложных операций читаются хуже — к этому вернёмся в конце урока.

Когда использовать лямбда-функции?

Лямбда-функции лучше всего подходят для случаев, когда:

  1. Функция простая (одно выражение)
  2. Функция используется только один раз (или несколько раз в одном месте)
  3. Функция передается как аргумент другой функции

Наиболее распространенные случаи использования — с функциями высшего порядка, такими как map(), filter(), sorted() и др.

Лямбда с функциями высшего порядка

map() — применение функции к каждому элементу

Функция map() применяет указанную функцию к каждому элементу итерируемого объекта:

Python 3.13
# Удвоение всех чисел в списке
numbers = [1, 2, 3, 4, 5]

# С обычной функцией
def double(x):
    return x * 2

doubled = list(map(double, numbers))
print(doubled)
[2, 4, 6, 8, 10]
# С лямбда-функцией (гораздо компактнее!)
doubled_lambda = list(map(lambda x: x * 2, numbers))
print(doubled_lambda)
[2, 4, 6, 8, 10]
# Преобразование температуры из Цельсия в Фаренгейт
celsius = [0, 10, 20, 30, 40]
fahrenheit = list(map(lambda c: (c * 9/5) + 32, celsius))
print(fahrenheit)
[32.0, 50.0, 68.0, 86.0, 104.0]

filter() — отбор элементов по условию

Функция filter() создает итератор из элементов, для которых функция возвращает True:

Python 3.13
# Фильтрация четных чисел
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# С лямбда-функцией
even_lambda = list(filter(lambda x: x % 2 == 0, numbers))
print(even_lambda)
[2, 4, 6, 8, 10]
# Фильтрация слов длиннее 3 букв
words = ["hi", "hello", "hey", "howdy", "hi there"]
long_words = list(filter(lambda word: len(word) > 3, words))
print(long_words)
['hello', 'howdy', 'hi there']

sorted() — сортировка с пользовательским ключом

Функция sorted() возвращает отсортированный список, а с помощью параметра key можно указать функцию для извлечения значения для сравнения:

Python 3.13
# Сортировка чисел по абсолютному значению
numbers = [5, -3, 2, -8, 1, 0, -2]

sorted_numbers = sorted(numbers, key=lambda x: abs(x))
print(sorted_numbers)
[0, 1, 2, -2, -3, 5, -8]
# Сортировка словарей по значению определенного ключа
students = [
    {"name": "Alice", "grade": 85},
    {"name": "Bob", "grade": 92},
    {"name": "Charlie", "grade": 78},
    {"name": "Diana", "grade": 95}
]

# Сортировка по оценке (по убыванию)
sorted_by_grade = sorted(students, key=lambda student: student["grade"], reverse=True)
for student in sorted_by_grade:
    print(f"{student['name']}: {student['grade']}")
Diana: 95
Bob: 92
Alice: 85
Charlie: 78

reduce() — последовательное применение функции

Функция reduce() (из модуля functools) последовательно применяет функцию к элементам, накапливая результат:

Python 3.13
from functools import reduce

# Сумма всех чисел в списке
numbers = [1, 2, 3, 4, 5]

total_lambda = reduce(lambda x, y: x + y, numbers)
print(total_lambda)
15
# Объединение строк
words = ["Hello", "world", "of", "Python"]
sentence = reduce(lambda x, y: x + " " + y, words)
print(sentence)
Hello world of Python

Передача лямбда-функций в другие функции

Лямбда-функции часто используются как аргументы в других функциях:

Python 3.13
def apply_operation(x, y, operation):
    """Применяет операцию к двум числам и возвращает результат"""
    return operation(x, y)

# Использование с разными лямбда-функциями
print(apply_operation(5, 3, lambda x, y: x + y))  # Сложение
8
print(apply_operation(5, 3, lambda x, y: x * y))  # Умножение
15
# Форматирование данных
def format_data(data, formatter):
    """Форматирует данные с помощью указанной функции"""
    return [formatter(item) for item in data]

names = ["alice", "bob", "charlie"]
print(format_data(names, lambda x: x.title()))  # Начало с заглавной
['Alice', 'Bob', 'Charlie']

Ограничения лямбда-функций

Лямбда-функции имеют несколько важных ограничений:

  1. Только одно выражение — нельзя использовать несколько строк кода
  2. Отсутствие документации — нельзя добавить docstring
  3. Ограниченная читаемость — для сложных операций лучше обычные функции
  4. Нет оператора присваивания — в лямбде нельзя использовать =
Python 3.13
# Пример сложной логики, где лучше не использовать лямбду
complex_lambda = lambda x: (
    x ** 2 if x > 0
    else x + 1 if x < 0
    else 42
)
print(complex_lambda(5))
25
# То же самое, но с обычной функцией - гораздо понятнее
def process_number(x):
    """Обрабатывает число по правилам:
    - Положительное -> квадрат
    - Отрицательное -> x + 1
    - Ноль -> 42
    """
    if x > 0:
        return x ** 2
    elif x < 0:
        return x + 1
    else:
        return 42

print(process_number(5))
25

Проверка понимания

Какое из следующих утверждений о лямбда-функциях в Python верно?