Python Lambda
Изучите lambda-функции в Python: синтаксис, использование с map, filter и sorted, отличия от def и ключевые ограничения.
Что такое lambda-функция?
Lambda-функция — это небольшая анонимная функция, определяемая с помощью ключевого слова lambda вместо def. Анонимная означает, что у неё нет имени — хотя её можно присвоить переменной, если нужно использовать повторно. Lambda-функции — это краткий способ записать простые однострочные функции прямо там, где они нужны, без накладных расходов полного определения функции.
Lambda-функции особенно удобны в качестве короткоживущих колбэков, передаваемых функциям высшего порядка, таким как map(), filter() и sorted().
Синтаксис
lambda arguments: expressionarguments— ноль или более разделённых запятыми параметров (как список параметров функцииdef, включая значения по умолчанию).expression— единственное выражение, значение которого возвращается автоматически. Операторы (такие как блокиif/else, циклыforилиreturn) не допускаются внутри тела lambda.
Сравнение двух эквивалентных вариантов:
def square(x):
return x ** 2
square_lambda = lambda x: x ** 2
print(square(5)) # Output: 25
print(square_lambda(5)) # Output: 25Базовые примеры
# No arguments
greet = lambda: "Hello, World!"
print(greet()) # Output: Hello, World!
# One argument
square = lambda x: x ** 2
print(square(5)) # Output: 25
# Two arguments
add = lambda x, y: x + y
print(add(10, 20)) # Output: 30
# Default argument value
greet_name = lambda name="World": "Hello, " + name + "!"
print(greet_name()) # Output: Hello, World!
print(greet_name("Alice")) # Output: Hello, Alice!Условная логика в lambda
Поскольку lambda должна быть единственным выражением, использовать оператор if/else нельзя. Однако можно использовать тернарное (условное) выражение:
classify = lambda n: "positive" if n > 0 else ("zero" if n == 0 else "negative")
print(classify(5)) # Output: positive
print(classify(0)) # Output: zero
print(classify(-3)) # Output: negativeГлубоко вложенные тернарные выражения быстро ухудшают читаемость — переходите к обычной функции def, как только логика усложняется.
Использование lambda с map()
map(function, iterable) применяет функцию к каждому элементу итерируемого объекта и возвращает объект map. Lambda идеально подходит в качестве аргумента-функции.
nums = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, nums))
print(doubled) # Output: [2, 4, 6, 8, 10]Эквивалентное списковое включение часто предпочтительнее с точки зрения читаемости:
doubled = [x * 2 for x in nums] # same resultПодробнее об этом подходе см. в разделе List Comprehension.
Использование lambda с filter()
filter(function, iterable) оставляет только те элементы, для которых функция возвращает True.
nums = [1, 2, 3, 4, 5]
evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens) # Output: [2, 4]Использование lambda с sorted()
Параметр key функции sorted() (и list.sort()) принимает вызываемый объект, возвращающий значение для сравнения каждого элемента. Lambda позволяет лаконично задавать одноразовые ключи сортировки.
# Sort strings by length
words = ["banana", "apple", "cherry", "date"]
by_length = sorted(words, key=lambda s: len(s))
print(by_length) # Output: ['date', 'apple', 'banana', 'cherry']
# Sort a list of tuples by the second element
pairs = [(1, "b"), (2, "a"), (3, "c")]
by_second = sorted(pairs, key=lambda p: p[1])
print(by_second) # Output: [(2, 'a'), (1, 'b'), (3, 'c')]Подробнее о сортировке списков см. в разделе Sort Lists.
Немедленный вызов lambda
Lambda можно вызвать сразу после определения, обернув её в скобки и добавив аргументы:
result = (lambda x, y: x + y)(3, 7)
print(result) # Output: 10Этот паттерн редко встречается в продакшн-коде, но иногда полезен в одноразовых скриптах или быстрых тестах.
Lambda в структуре данных
Поскольку lambda является объектом первого класса в Python, её можно хранить в списках или словарях для построения простых таблиц диспетчеризации:
ops = {
"add": lambda x, y: x + y,
"sub": lambda x, y: x - y,
"mul": lambda x, y: x * y,
}
print(ops["add"](3, 4)) # Output: 7
print(ops["sub"](10, 3)) # Output: 7
print(ops["mul"](2, 6)) # Output: 12Lambda vs. def — когда что использовать
| Ситуация | Предпочтительно |
|---|---|
| Короткий однострочный колбэк, передаваемый inline | lambda |
| Функция требует более одного выражения или оператора | def |
| Функция вызывается из многих мест по имени | def |
| Нужна строка документации или аннотации типов | def |
Передаётся как key= в sorted() / min() / max() | lambda (распространённая идиома) |
Руководство по стилю PEP 8 рекомендует не присваивать lambda переменной, когда def был бы понятнее. Например, предпочтительнее написать def add(x, y): return x + y, чем add = lambda x, y: x + y, если функция находится на уровне модуля.
Ключевые ограничения
- Только одно выражение. Нельзя использовать присваивания, циклы или многострочную логику.
- Без операторов.
print()— это вызов функции (допустимо), ноassert,raiseиreturnявляются операторами и не могут появляться в теле lambda. - Без аннотаций. Аннотации типов (
x: int) не допускаются в списке параметров lambda. - Сложнее отлаживать. В трассировке стека вместо осмысленного имени функции отображается
<lambda>. - Нельзя сериализовать. Стандартный модуль
pickleне может сериализовать lambda-объекты — это важно при использовании multiprocessing.
Связь с замыканиями и декораторами
Как и обычная функция, определённая с помощью def, lambda захватывает переменные из охватывающей области видимости:
def make_multiplier(n):
return lambda x: x * n # 'n' is captured from the enclosing scope
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # Output: 10
print(triple(5)) # Output: 15Подробнее о том, как работают замыкания в Python, см. в разделе Python Closures. Lambda-функции также часто встречаются внутри Python Decorators в качестве лёгких обёрток. Полный обзор определения функций см. в разделе Python Functions.