Lambda-выражения в Python. Анонимные функции

Лямбда-выражение — это особая конструкция языка программирования Python, в результате выполнения которой создается анонимная объект–функция. Такая функция — это не только более компактный вариант записи для простых функций, тело которых можно записать в одно выражение. Иногда lambda-выражения удобнее и позволяют создать функции там, где def использовать нельзя. В примере ниже определяются две функции, делающие одно и то же. В первом случае используется lambda-выражение, во втором — обычный способ.

>>> a = lambda i, j: i + j
>>> 
>>> def b(i, j):
...     return i + j
...  
>>> a(10, 5)
15
>>> b(10, 5)
15

Почему lambda-функция анонимная? Когда функция создается с помощью def, то она не может существовать без имени. Такая функция обязательно связывается с идентификатором, указанным в ее заголовке. Так сказать, имеет место неявное присваивание. В примере выше обычная функция имеет имя b.

Lambda-функция имени не имеет, его просто нет в выражении lambda параметры: операция. То, что мы потом явно связываем эту функцию с переменной, исключительно наше дело. Могли бы так не делать. Рассмотрим пример:

>>> a = lambda base: base**2.5
>>> type(a)
<class 'function'>
>>> a(4)
32.0
>>> 
>>> n = (lambda base: base**2.5)(4)
>>> type(n)
<class 'float'>
>>> n
32.0

Здесь в первом случае переменной присваивается функция, а во втором — значение, которое возвращает функция, а не она сама. То есть лямбда-выражение возвращает неименованную функцию, которая сразу вызывается, так как после нее стоят аргументы. То, что функция вернула, присваивается переменной. Сама функция при этом теряется.

Пример списка функций:

>>> a = [(lambda i,j:i+j), (lambda i,j:i-j), (lambda i: i//2)]
>>> a[0](1,4)
5
>>> a[1](1,4)
-3
>>> a[2](10)
5

Подобное бывает удобно для последующей, своего рода, пакетной обработки данных. Если индексы ни о чем не говорят, можно использовать словарь:

fx = {'pos':lambda x: x-1,'neg':lambda x: abs(x)-1,'zero':lambda x: x}
values = [-3, 10, 0, 1]
for i in values:
    if i < 0:
        print(fx['neg'](i))
    elif i > 0:
        print(fx['pos'](i))
    else:
        print(fx['zero'](i))

Пример выполнения:

2
9
0
0

В лямбда-функциях можно использовать условный оператор if-else, но в необычном для него варианте синтаксиса. Здесь до if записывается выражение, результат выполнения которого возвращается, если условие при if является истиной. Другими словами, тело if выносится вперед, располагается до условия. После if с его условием сразу идет else, и уже после него следует выражение, результат выполнения которого возвращается, если условие при if является ложью. Ветка else должна присутствовать обязательно.

a = [56, 18, 13, 63, 15, 12]
print(a)

even = 0
for num in a:
    even += (lambda i: 1 if i%2 == 0 else 0)(num)

print('Количество четных:', even)  # 3

Лямбда-функции нередко используются в качестве аргумента параметра key метода sort() или функции sorted(). Эту возможность рассмотрим в следующем уроке.

Практическая работа

Создайте список лямбда-выражений. Одно складывает аргументы, другое – вычитает, третье – умножает, четвертое – делит, но только если делитель не равен нулю, иначе возвращает None. Запросите у пользователя два числа и в цикле "прогоните" их через все lambda-функции списка.