Python для сбора данных

Алла Тамбовцева, НИУ ВШЭ

Lambda-функции

Lambda-функции в Python

Иногда возникает необходимость написать небольшую функцию, которая будет использоваться один раз, да и то в сочетании с какими-нибудь другими функциями или методами. В таком случае совсем необязательно создавать эту функцию с помощью def и присваивать ей имя. Можно воспользоваться специальными lambda-функциями, которые создаются в одну строчку и могут существовать без имени (их ещё назвают анонимными).

Для начала создадим какую-нибудь не-анонимную функцию, чтобы познакомиться с синтаксисом. Пусть это будет функция sq, которая принимает на вход какое-то число x и возвращает его квадрат.

In [2]:
sq = lambda x: x ** 2 # готово

Использовать эту функцию можно как функции, заданные через def:

In [3]:
sq(10)
Out[3]:
100
In [4]:
sq(-7)
Out[4]:
49

Если функция принимает на вход более одного аргумента, они просто перечисляются через запятую после lambda:

In [5]:
my_sum = lambda x, y: x + y
In [6]:
my_sum(0, 7)
Out[6]:
7
In [7]:
my_sum(6, 7)
Out[7]:
13

Теперь посмотрим на сочетание lambda-функций с встроенными функциями Python. Lambda-функции часто используют в сочетании с функциями filter() и map(), которые позволяют отфильтровывать значения списков/кортежей или преобразовывать их элементы (более быстрая и удобная альтернатива списковым включениям). Если вы помните, когда мы обсуждали списки, мы говорили про метод .index(), который возвращает индекс какого-то элемента по его значению. Проблема в том, что в случае списка с повторяющимися значениями он возвращает только первое совпадение:

In [8]:
L = [0, 2, 7, 5, 4, 3, 2]
L.index(2) # только первая 2
Out[8]:
1

Если мы захотим таким образом вернуть все элементы, удовлетворяющие некоторому условию, ничего не получится (понадобятся циклы, условия, списковые включения). А можно просто написать lambda-функцию, которая будет возвращать значения True или False в зависимости от соответствия условию, а потом передать полученный результат функции filter(), которая отберет элементы с True:

In [47]:
list(filter(lambda x: x > 3, L))  # элементы списка L больше 3
Out[47]:
[7, 5, 4]
In [48]:
list(filter(lambda x: x % 2 == 0, L))  # четные элементы списка L
Out[48]:
[0, 2, 4, 2]

Условия можно совмещать:

In [49]:
list(filter(lambda x: (x > 3) & (x < 7), L))   # 3 < x < 7
Out[49]:
[5, 4]

Обратите внимание: перед filter() всегда добавляется list(). Это нужно для того, чтобы увидеть результаты явно и получить их в виде списка. Иначе мы просто получим «закрытый» объект типа filter() ( вспомните историю про zip()).

In [9]:
filter(lambda x: x > 3, L)
Out[9]:
<filter at 0x10dde1eb8>

Теперь попробуем совместить lambda-функцию и функцию map(), которая позволяет получать новый список на основе старого, преобразовывая его элементы:

In [50]:
list(map(lambda x: x ** 2, L))  # квадраты элементов списка L
Out[50]:
[0, 4, 49, 25, 16, 9, 4]