Что такое lambda в питоне
Лямбда-выражения в языке Python представляют небольшие анонимные функции, которые определяются с помощью оператора lambda . Формальное определение лямбда-выражения:
lambda [параметры] : инструкция
Определим простейшее лямбда-выражение:
message = lambda: print("hello") message() # hello
Здесь лямбда-выражение присваивается переменной message. Это лямбда-выражение не имеет параметров, ничего не возвращает и просто выводит строку «hello» на консоль. И через переменную message мы можем вызвать это лямбда-выражение как обычную функцию. Фактически оно аналогично следующей функции:
def message(): print("hello")
Если лямбда-выражение имеет параметры, то они определяются после ключевого слова lambda . Если лямбда-выражение возвращает какой-то результат, то он указывается после двоеточия. Например, определим лямбда-выражение, которое возвращает квадрат числа:
square = lambda n: n * n print(square(4)) # 16 print(square(5)) # 25
В данном случае лямбда-выражение принимает один параметр — n. Справа от двоеточия идет возвращаемое значение — n* n . Это лямбда-выражение аналогично следующей функции:
def square2(n): return n * n
Аналогичным образом можно создавать лямбда-выражения, которые принимают несколько параметров:
sum = lambda a, b: a + b print(sum(4, 5)) # 9 print(sum(5, 6)) # 11
Хотя лямбда-выражения позволяют немного сократить определения функций, тем не менее они ограничены тем, что они могут выполнять только одно выражение. Однако они могут быть довольно удобны в тех случаях, когда необходимо использовать функцию для передачи в качестве параметра или возвращения в другой функции. Например, передача лямбда-выражения в качестве параметра:
def do_operation(a, b, operation): result = operation(a, b) print(f"result = ") do_operation(5, 4, lambda a, b: a + b) # result = 9 do_operation(5, 4, lambda a, b: a * b) # result = 20
В данном случае нам нет необходимости определять функции, чтобы передать их в качестве параметра, как в прошлой статье.
То же самое касается и возвращение лямбда-выражений из функций:
def select_operation(choice): if choice == 1: return lambda a, b: a + b elif choice == 2: return lambda a, b: a - b else: return lambda a, b: a * b operation = select_operation(1) # operation = sum print(operation(10, 6)) # 16 operation = select_operation(2) # operation = subtract print(operation(10, 6)) # 4 operation = select_operation(3) # operation = multiply print(operation(10, 6)) # 60
Все, что нужно знать о lambda-функциях в Python
В этой статье вы узнаете о том, что такое лямбда-функции в Python. На самом деле, если вы знаете, что такое функции и умеете с ними работать, то знаете и что такое лямбда.
Лямбда-функция в Python — это просто функция Python. Но это некий особенный тип с ограниченными возможностями. Если есть желание погрузиться глубже и узнать больше, то эта статья целиком посвящена lambda .
Что такое лямбда в Python?
Прежде чем переходить как разбору понятия лямбда в Python, попробуем понять, чем является обычная функция Python на более глубоком уровне.
Для этого потребуется немного поменять направление мышление. Как вы знаете, все в Python является объектом.
Например, когда мы запускаем эту простейшую строку кода
x = 5
Создается объект Python типа int , который сохраняет значение 5. x же является символом, который ссылается на объект.
Теперь проверим тип x и адрес, на которой он ссылается. Это можно сделать с помощью встроенных функций type и id .
>>> type(x) class 'int'> >>> id(x) 4308964832
В итоге x ссылается на объект типа int , а расположен он по адресу, который вернула функция id .
Просто и понятно.
А что происходит при определении вот такой функции:
>>> def f(x): ... return x * x ...
Повторим упражнение и узнаем type и id объекта f .
>>> def f(x): ... return x * x ... >>> type(f) class 'function'> >>> id(f) 4316798080
Оказывается, в Python есть класс function , а только что определенная функция f — это его экземпляр. Так же как x был экземпляром класса integer . Другими словами, о функциях можно думать как о переменных. Разница лишь в том, что переменные хранят данные, а функции — код.
Это же значит, что функции можно передать в качестве аргументов другим функциям или даже использовать их как тип возвращаемого значения.
Рассмотрим простой пример, где функция f передается другой функции.
def f(x): return x * x def modify_list(L, fn): for idx, v in enumerate(L): L[idx] = fn(v) L = [1, 3, 2] modify_list(L, f) print(L) #вывод: [1, 9, 4]
Попробуйте разобраться самостоятельно с тем, что делает этот код, прежде чем читать дальше.
Итак, modify_list — это функция, которая принимает список L и функцию fn в качестве аргументов. Затем она перебирает список элемент за элементом и применяет функцию к каждому из них.
Это общий способ изменения объектов списка, ведь он позволяет передать функцию, которая займется преобразованием. Так, если передать modify_list функцию f , то результатом станет список, где все значения будут возведены в квадрат.
Но можно передать и любую другую, которая изменит оригинальный список другим способом. Это очень мощный инструмент.
Теперь, когда с основами разобрались, стоит перейти к лямбда. Лямбда в Python — это просто еще один способ определения функции. Вот базовый синтаксис лямбда-функции в Python:
lambda arguments: expression
Лямбда принимает любое количество аргументов (или ни одного), но состоит из одного выражения. Возвращаемое значение — значение, которому присвоена функция. Например, если нужно определить функцию f из примера выше, то это можно сделать вот так:
>>> f = lambda x: x * x >>> type(f) class 'function'>
Но возникает вопрос: а зачем нужны лямбда-функции, если их можно объявлять традиционным образом? Но на самом деле, они полезны лишь в том случае, когда нужна одноразовая функция. Такие функции еще называют анонимными. И, как вы увидите дальше, есть масса ситуаций, где они оказываются нужны.
Лямбда с несколькими аргументами
Определить лямбда-функцию с одним аргументом не составляет труда.
>>> f = lambda x: x * x >>> f(5) 25
А если их должно быть несколько, то достаточно лишь разделить значения запятыми. Предположим, что нужна функция, которая берет два числовых аргумента и возвращает их произведение.
>>> f = lambda x, y: x * y >>> f(5, 2) 10
Отлично! А как насчет лямбда-функции без аргументов?
Лямбда-функция без аргументов
Допустим, нужно создать функцию без аргументов, которая бы возвращала True . Этого можно добиться с помощью следующего кода.
>>> f = lambda: True >>> f() True
Несколько лямбда-функций
В определенный момент возникнет вопрос: а можно ли иметь лямбда-функцию из нескольких строк.
Ответ однозначен: нет.
Лямбда-функции в Python всегда принимают только одно выражение. Если же их несколько, то лучше создать обычную функцию.
Примеры лямбда-функций
Теперь рассмотрим самые распространенные примеры использования лямбда-функций.
Лямбда-функция и map
Распространенная операция со списками в Python — применение операции к каждому элементу.
map() — это встроенная функция Python, принимающая в качестве аргумента функцию и последовательность. Она работает так, что применяет переданную функцию к каждому элементу.
Предположим, есть список целых чисел, которые нужно возвести в квадрат с помощью map .
>>> L = [1, 2, 3, 4] >>> list(map(lambda x: x**2, L)) [1, 4, 9, 16]
Обратите внимание на то, что в Python3 функция map возвращает объект Map , а в Python2 — список.
Так, вместо определения функции и передачи ее в map в качестве аргумента, можно просто использовать лямбда для быстрого определения ее прямо внутри. В этом есть смысл, если упомянутая функция больше не будет использоваться в коде.
Вот еще один пример.
Лямбда-функция и filter
filter() — это еще одна встроенная функция, которая фильтрует последовательность итерируемого объекта.
Другими словами, функция filter отфильтровывает некоторые элементы итерируемого объекта (например, списка) на основе какого-то критерия. Критерий определяется за счет передачи функции в качестве аргумента. Она же применяется к каждому элементу объекта.
Если возвращаемое значение — True , элемент остается. В противном случае — отклоняется. Определим, например, простую функцию, которая возвращает True для четных чисел и False — для нечетных:
def even_fn(x): if x % 2 == 0: return True return False print(list(filter(even_fn, [1, 3, 2, 5, 20, 21]))) #вывод: [2, 20]
С лямбда-функциями это все можно сделать максимально сжато. Код выше можно преобразовать в такой, написанный в одну строку.
print(list(filter(lambda x: x % 2 == 0, [1, 3, 2, 5, 20, 21])))
И в этом сила лямбда-функций.
Лямбда-функция и сортировка списков
Сортировка списка — базовая операция в Python. Если речь идет о списке чисел или строк, то процесс максимально простой. Подойдут встроенные функции sort и sorted .
Но иногда имеется список кастомных объектов, сортировать которые нужно на основе значений одного из полей. В таком случае можно передать параметр key в sort или sorted . Он и будет являться функцией.
Функция применяется ко всем элементам объекта, а возвращаемое значение — то, на основе чего выполнится сортировка. Рассмотрим пример. Есть класс Employee .
class Employee: def __init__(self, name, age): self.name = name self.age = age
Теперь создадим экземпляры этого класса и добавим их в список.
Alex = Employee('Alex', 20) Amanda = Employee('Amanda', 30) David = Employee('David', 15) L = [Alex, Amanda, David]
Предположим, что мы хотим отсортировать его на основе поля age сотрудников. Вот что нужно сделать для этого:
L.sort(key=lambda x: x.age) print([item.name for item in L]) # вывод: ['David', 'Alex', 'Amanda']
Лямбда-выражение было использовано в качестве параметра key вместо отдельного ее определения и затем передачи в функцию sort .
Пара слов о выражениях и инструкциях
Как уже упоминалось, лямбда могут иметь только одно выражение (expression) в теле.
Обратите внимание, что речь идет не об инструкции (statement).
Выражение и инструкции — две разные вещи, в которых часто путаются. В программировании инструкцией является строка кода, выполняющая что-то, но не генерирующая значение.
Например, инструкция if или циклы for и while являются примерами инструкций. Заменить инструкцию на значение попросту невозможно.
А вот выражения — это значения. Запросто можно заменить все выражения в программе на значения, и программа продолжит работать корректно.
- 3 + 5 — выражение со значением 8
- 10 > 5 — выражение со значением True
- True and (5 < 3) — выражение со значением False
Тело лямбда-функции должно являться выражением, поскольку его значение будет тем, что она вернет. Обязательно запомните это для работы с лямбда-функциями в будущем.
lambda-выражения, анонимные функции
Небольшие анонимные функции могут быть созданы с ключевым словом lambda . Эта функция возвращает сумму двух аргументов: lambda a, b: a + b . Лямбда-функции можно использовать везде, где требуются функциональные объекты. Они синтаксически ограничены одним выражением.
Семантически, они просто синтаксический сахар для нормального определения функции.
def func(a, b): return a + b # равноценно f = lambda a, b: a+b a = 5 b = 4 print(func(a, b)) print(f(a, b))
Единственное преимущество использования лямбда-выражения вместо локально определенной функции состоит в том, что вам не нужно придумывать имя для функции. В отличие от лямбда-форм в других языках, где они добавляют функциональность. Лямбда-выражения Python являются лишь сокращенной записью, если вы слишком ленивы, чтобы определить функцию.
Отличие lambda-выражения от нормального определения функции:
- не могут содержать return , pass , assert или raise ;
- не имеют имени функции, отсюда название — анонимные функции;
- не могут иметь в теле более одной строки с выражением.
- не поддерживает аннотации типов.
Как и обычный объект функции, лямбда-выражения поддерживают различные способы передачи аргументов:
- только по позиции
- по позиции или по ключу
- только по ключу
- *args — произвольное число позиционных аргументов
- **kwargs — произвольное число именованных аргументов
Как и вложенные функции, лямбда-функции могут ссылаться на переменные из содержащей области.
Пример использует lambda-выражение для возврата функции:
>>> def make_incrementor(n): # lambda-выражение принимает переменную 'x', # которая передается как f(x), см. ниже. . return lambda x: x + n . >>> f = make_incrementor(42) >>> f(0) 42 >>> f(1) 43 >>>
Код с частым использованием лямбда-функции сложно читать и понимать, а иногда можно и самому запутаться.
# Сравните код с lambda-выражением: from functools import reduce numbers = [2, 1, 3, 4, 7, 11, 18] product = reduce(lambda x, y: x * y, numbers, 1) # С кодом простой функции: def multiply_all(numbers): product = 1 for n in numbers: product *= n return product numbers = [2, 1, 3, 4, 7, 11, 18] product = multiply_all(numbers)
Второй код длиннее, но является более простым для понимания, в то время как комбинация reduce/lambda будет, скорее всего сложен для понимания многим программистам. В целом, передача одной функции другой, как правило, делает код более сложным, что вредит читаемости.
Лямбда-функции в основном используются:
-
со встроенными функциями zip() , map() , filter() , а также reduce() — представленными в модуле functools .
# мили в километры mile = [1.0, 6.5, 17.4, 2.4, 9] kilometer = list(map(lambda x: x * 1.6, mile)) print (kilometer) # Вывод [1.6, 10.4, 27.84, 3.84, 14.4]
- list.sort() : дополнительный метод списка
- sorted() , min() , max()
# Сортировка словаря d = 'a': 10, 'b': 15, 'c': 4> list_d = list(d.items()) list_d.sort(key=lambda i: i[1]) print(list_d) # Вывод [('c', 4), ('a', 10), ('b', 15)]
doit = [(lambda x,y: x+y), (lambda x,y: x-y), (lambda x,y: x*y), (lambda x,y: x/y)] rez = doit[0](5, 12)
doit = 'neg':lambda x: x-1, 'abs':lambda x: abs(x)-1, 'zero':lambda x: x> a = [-3, 10, 0, 1] for i in a: if i 0: print(doit['abs'](i)) elif i > 0: print(doit['neg'](i)) else: print(doit['zero'](i))
- КРАТКИЙ ОБЗОР МАТЕРИАЛА.
- Функции это объекты
- Функции могут иметь атрибуты
- Функции могут храниться в структурах данных
- Функции могут быть вложенными
- Передача функции в качестве аргумента другой функции
- Область видимости переменных функции
- Операторы global и nonlocal
- Параметры (аргументы) функции
- Ключевые аргументы в определении функции Python
- Значение аргумента по умолчанию в функциях Python
- Варианты передачи аргументов в функцию Python
- Переменные аргументов *args и **kwargs в функции Python
- Распаковка аргументов для передачи в функцию Python
- Как оцениваются аргументы при вызове функции?
- Строгие правила передачи аргументов в функцию Python
- Инструкция return
- Анонимные функции (lambda-выражения)
- Строки документации в функциях Python
- Рекурсия
- Замыкания в функциях Python
- Перегрузка функций
Лямбда-функции в Python: примеры
Лямбда-функции – это анонимные функции, которые содержат только одно выражение.
Вы можете подумать, что лямбда-функции – это что-то сложное, доступное только продвинутым программистам. Но из этой статьи вы узнаете, как легко начать использовать их в своём коде.
В Python мы обычно создаём функции так:
def my_func(a): # Тело функции
Они объявляются при помощи ключевого слова def , им можно давать название, добавлять список аргументов в скобках. В теле функции может быть много строчек кода, с любым количеством выражений. Но иногда вам может понадобиться функция с одним-единственным выражением внутри.
Например, функция, удваивающая аргумент:
def double(x): return x*2
Такую функцию, например, можно использовать в методе map .
def double(x): return x*2 my_list = [1, 2, 3, 4, 5, 6] new_list = list(map(double, my_list)) print(new_list) # [2, 4, 6, 8, 10, 12]
Именно здесь целесообразно использовать лямбда-функцию, т.к. её можно создать прямо в том же месте, где она используется. А это означает меньше строк кода. Кроме того, нам не придётся создавать функцию с именем, которая будет занимать место в памяти и пригодится лишь однажды.
Как использовать лямбда-функции в Python
Как вы уже поняли, лямбды применяются там, где нужна маленькая функция на короткое время – например, в функциях высшего порядка, таких как map или filter .
Синтаксис лямбда-функции имеют следующий:
lambda args: expression
Сперва пишется слово lambda , затем идет одинарный пробел, за ним — список аргументов через запятую, следом – двоеточие и само выражение, являющееся телом функции.
Обратите внимание, что лямбда-функциям нельзя дать имя, потому что они анонимные (без имени) по определению.
Аргументов в них может быть сколько угодно, но выражение в теле обязательно одно.
Пример 1
Можно написать лямбду, которая удваивает свой аргумент: lambda x: x*2 , и использовать её в функции map , чтобы удвоить все элементы в списке:
my_list = [1, 2, 3, 4, 5, 6] new_list = list(map(lambda x: x*2, my_list)) print(new_list) # [2, 4, 6, 8, 10, 12]
Заметьте разницу между этим кодом и функцией double , которую мы написали выше: лямбда гораздо компактнее.
Пример 2
А ещё можно создать лямбда-функцию, которая ищет числа больше нуля: lambda x: x > 0 и использовать в filter , чтобы создать список исключительно положительных чисел.
my_list = [18, -3, 5, 0, -1, 12] new_list = list(filter(lambda x: x > 0, my_list)) print(new_list) # [18, 5, 12]
Лямбда-функция определяется там, где используется. Таким образом, в памяти не придётся хранить функцию с именем. Поэтому для одноразового использования целесообразно писать лямбда-функции, чтобы избежать загромождения.
Пример 3
Лямбда также может быть возвращаемым значением другой функции.
Если вам потребуется создать несколько функций, умножающих числа (например, удваивающих и утраивающих), лямбда может помочь.
Вместо объявления множества таких функций можно создать всего лишь одну: multiplyBy . А затем можно вызывать эту функцию по нескольку раз с разными аргументами, чтобы создавать функции умножения на два, на три и т.д.
def muliplyBy (n): return lambda x: x*n double = multiplyBy(2) triple = muliplyBy(3) times10 = multiplyBy(10)
Лямбда-функция принимает значение n из функции multiplyBy . Таким образом, в double параметр n равен 2 , в triple — 3 , а в times10 – 10 . Теперь при вызове полученных функций с определённым аргументом будет производиться умножение на соответствующее число.
double(6) > 12 triple(5) > 15 times10(12) > 120
Без лямбды вам бы пришлось определять внутри multiplyBy другие функции:
def muliplyBy (x): def temp (n): return x*n return temp
Лямбда-функция занимает всего полстроки и увеличивает читабельность кода.
Заключение
Лямбда-функции – это компактный вариант записи функций, содержащих только одно выражение. Новички обычно ими не пользуются, но теперь вы понимаете, как их можно применить для решения задач разной сложности.
