Наука о данных

Лямбда-функции в Python: все, что вам нужно знать

Учитесь на реальных и наиболее практических примерах

Лямбда — используйте с умом!! 💡

Python — мощный язык для анализа данных не только потому, что он прост в использовании, но и предлагает огромное количество встроенных функций и методов для работы с данными.

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

Поэтому здесь я перечислил 3 практических варианта использования лямбда-функции с примерами. Также вы узнаете, почему и когда не следует использовать лямбда-функцию. 🏆

Несмотря на то, что это быстрое чтение, вы можете напрямую перейти к своему любимому разделу, используя указатель ниже.

· What is Lambda Function in Python?
· Filter a List using Lambda Function
· Use Lambda function in map()
· Use Lambda function in apply()
· When not to use a Lambda functionAssigning a lambda expression to a variablePassing function inside lambda functionUse lambda function when one-liner is poor choice

Прежде чем начать с вариантов использования, давайте быстро посмотрим, что такое лямбда-функция и как ее использовать.

Что такое лямбда-функция в Python?

Это анонимная функция или функция без имени. В отличие от других определяемых пользователем функций в Python, лямбда-функция может быть определена и вызвана в той же строке кода.

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

Каждая лямбда-функция начинается с ключевого слова lambda, за которым следуют параметры функции и тело функции. Параметры функции и тело разделяются двоеточием, т.е. : .

Например, в функции lambda x: x**2 x — это параметр функции, а x**2 — это выражение, т. е. тело функции. Вы можете применить эту функцию к одной переменной, как показано ниже:

(lambda x:x**2)(5)
# Output
25

Таким образом, операция, упомянутая в выражении (в данном случае x**2 является квадратом x), выполняется над числом 5.

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

Теперь давайте рассмотрим наиболее практические варианты использования этой удивительной функции.

Фильтровать список с помощью лямбда-функции

Одним из самых простых вариантов использования лямбда-функции является фильтрация заданного списка на основе определенных критериев. Для этого вы можете использовать лямбда-функцию с другой встроенной функцией filter().

В Python filter() применяется к итерируемому объекту, такому как список или словарь, для создания нового итерируемого объекта, который по существу содержит только те элементы исходного итерируемого объекта, которые удовлетворяют определенному условию. И это условие определяется функцией.

Поскольку синтаксис для filter() — filter(function, iterable), логически лямбда-функцию можно использовать для определения условия, которое можно использовать в filter().

Например, у вас есть список с числами от 2 до 50 с интервалом 3. И вы хотите получить только те числа, квадрат которых меньше 100. Таким образом, условие можно определить как лямбда-функцию, как показано ниже:

lambda x:x**2<100

И его можно использовать в таком фильтре,

import numpy as np
yourlist = list(np.arange(2,50,3))
list(filter(lambda x:x**2<100, yourlist))
# Output 
[2, 5, 8]

Если вы посмотрите на промежуточный шаг filter(lambda x:x**2<100, yourlist), он возвращает объект фильтра, который действительно нужно преобразовать в структуру данных, такую ​​как список или набор, что делается в последней строке кода выше.

Конечно, для сложных вычислений в функции вы должны использовать обычную пользовательскую функцию, но когда у вас есть функция только с одним выражением, лямбда-функция является идеальным выбором. 💯

Далее, вместо того, чтобы фильтровать список, также может быть интересно узнать, как применить функцию к каждому элементу итерируемого объекта.

Используйте лямбда-функцию в map()

В Python map() — это функция, которая буквально отображает или обрабатывает переданную функцию для каждого элемента в итерируемом объекте.

Она имеет тот же синтаксис, что и предыдущая функция, map(function, iterable). Итак, как и в filter(), вы можете передать лямбда-функцию в map().

Например, предположим, что вы хотите получить сложение квадрата и куба каждого элемента в списке. поэтому лямбда-функция будет,

lambda x: x**2+x**3

Аналогично функции filter(), функция map() возвращает объект карты, который необходимо преобразовать в другую структуру данных. Таким образом, требуемый результат может быть получен как

list(map(lambda x: x**2+x**3, yourlist))
# Output
[12,
 150,
 576,
 1452,
 2940,
 5202,
 8400,
 12696,
 18252,
 25230,
 33792,
 44100,
 56316,
 70602,
 87120,
 106032]

Но это был довольно простой пример, верно??

В другом примере предположим, что у вас есть два списка mylist и yourlist одинаковой длины, например:

mylist = list(np.arange(4,52,3))
yourlist = list(np.arange(2,50,3))

И вы хотите получить добавление квадратных элементов в одной и той же позиции в обоих списках. Это может быть очень просто с помощью функции map(), как показано ниже.

list(map(lambda x,y: x**2+y**2, yourlist,mylist))

Обратите внимание, что, поскольку вы определили две переменные в лямбда-функции как x и y, вам необходимо предоставить две итерации в функции карты, то есть yourlist и mylist.

Последовательность этих итераций в map() или даже в filter() имеет значение, поскольку первая итерация всегда передается как x, тогда как вторая итерация передается как y. 💯

Двигаясь вперед, вы также можете использовать лямбда-функцию для преобразования объекта серии pandas.

Используйте лямбда-функцию в apply()

Серия pandas на самом деле представляет собой одномерный массив индексированных данных. В отличие от списка, серия всегда содержит данные одного типа. И это составляет основу Pandas DataFrame, где каждый столбец DataFrame представляет собой серию pandas.

Чтобы преобразовать серию панд, вы можете использовать функцию apply(). Как следует из названия, он используется для применения функции к серии pandas.

Давайте создадим серию панд, чтобы понять концепцию на примере.

myseries = pd.Series(mylist)
myseries

Синтаксис apply() немного отличается от предыдущих двух функций, но логика такая же — функция, переданная в apply(), применяется к каждому элементу серии. 💯

Например, предположим, что вы хотите прибавить 5 к каждому элементу myseries, а затем разделить результат на квадрат того же элемента. Таким образом, лямбда-функция будет lambda x: (x+5)/x**2, и ее можно использовать в приложении, как показано ниже:

myseries.apply(lambda x: (x+5)/x**2)

В отличие от двух предыдущих функций, вам не нужно передавать итерируемый объект или серию в apply(), но вы можете напрямую использовать ее в серии, используя .apply(function).

Вместо применения к одной серии имеет смысл использовать ее в DataFrame. Например, у вас есть фиктивные данные о продажах (можно бесплатно загрузить по лицензии MIT с Github) в DataFrame df.

df = pd.read_csv("Dummy_Sales_Data_v1.csv")
df.head()

А вы хотите сделать имя каждого менеджера по продажам прописным. Это легко сделать с помощью лямбда-функции в методе .apply().

df["Sales_Manager"] = df["Sales_Manager"].apply(lambda x: x.upper())
df.head()

Вы можете просто использовать .apply() в любом столбце, определить быстрое преобразование с помощью лямбда-функции и назначить результаты обратно в исходный столбец. 💯

.apply() с лямбда-функцией в 1,4 раза быстрее, чем str.upper()

Когда вы сравните .apply() с лямбда-функцией со строковыми методами для выполнения одного и того же преобразования, вы увидите, что первый работает быстрее, чем последний. И если вы сравните его с циклом for, то .apply() в 300 раз быстрее.

Я лично нахожу .apply() с лямбда-функцией весьма полезным в большинстве моих задач по анализу данных.

Когда вы узнали о том, как и когда вы можете использовать лямбда-функцию в Python, также важно знать, когда ее не следует использовать. 🎯

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

Конечно, есть несколько вариантов использования функции Lambda, которые не рекомендуются Стандартными рекомендациями по кодированию Python.

Нет ничего плохого в использовании лямбда-функции в следующих 3 случаях, просто это не лучшая практика, и поэтому ее следует избегать.

Присвоение лямбда-выражения переменной

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

По определению лямбда — анонимная функция, поэтому хранить ее в переменной для будущего использования — не лучшая идея.

Например, предположим, что вы хотите получить сумму квадратов двух чисел, и вы хотите сделать это преобразование несколько раз в своем проекте, тогда

Плохая практика ❌

squared_sum = lambda x,y: x**2 + y**2
squared_sum(3,4)
#Output
25

Лучшая практика ✅

def squared_sum(x,y):
    return x**2 + y**2
#Output
25

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

Кроме того, я также наблюдал, как многие специалисты по данным передают стандартную функцию, такую ​​​​как sqrt, в лямбда-функции, что не является хорошей практикой.

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

Этот сценарий возникает, когда вы хотите использовать функцию в методе map(), filter() или apply(). Сюда входят все встроенные функции и пользовательские функции, которые принимают ровно один аргумент.

Например, предположим, что у вас есть список чисел и вы хотите получить квадратный корень из этих чисел. Это можно получить с помощью встроенной функции sqrt, доступной в библиотеке math.

Плохая практика ❌

import math
mylist = [10, 25, 40, 49, 65, 81]
sqrt_list = list(map(lambda x: math.sqrt(x), mylist))
sqrt_list
#output
[3.1622776601683795, 5.0, 6.324555320336759, 7.0, 8.06225774829855, 9.0]

Лучшая практика ✅

import math
mylist = [10, 25, 40, 49, 65, 81]
sqrt_list = list(map(math.sqrt, mylist))
sqrt_list
#output
[3.1622776601683795, 5.0, 6.324555320336759, 7.0, 8.06225774829855, 9.0]

Встроенная функция sqrt из библиотеки math может использоваться непосредственно в функции map(). Использование его внутри лямбда-функции необязательно и может повлиять на производительность.

Если вы сравните две приведенные выше практики передачи другой функции в лямбда-функцию и выполните 100000 итераций для каждой, вы увидите, что лучшая практика всегда повышает производительность. 💯

Передача функции напрямую в map() в 1,8 раза быстрее!

То же самое относится и к пользовательским функциям.

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

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

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

И когда вы используете такую ​​лямбда-функцию в однострочном коде, ваш однострочный код больше не умещается в одну строку.

В соответствии с рекомендациями PEP8, ограничьте все строки до 79 символов.

Поскольку код состоит из нескольких строк, становится трудно эффективно читать код и при необходимости отлаживать его.

Например, у вас есть фиктивные данные о продажах (можно скачать бесплатно по лицензии MIT с Github) в DataFrame df.

df = pd.read_csv("Dummy_Sales_Data_v1.csv")
df.head()

И вы хотите создать новый столбец с Окончательным статусом таким образом, чтобы, если столбец Статус содержал 'Доставлено' или 'Отправлено' окончательный статус будет 'Завершено', в противном случае он будет 'Не завершен'

Один лайнер и плохая практика ❌

df["FinalStatus"] = df["Status"].map(lambda x: 'Completed' if x == 'Delivered' or x == 'Shipped' else 'Not Completed')

Этот вкладыш содержит 118 символов и выходит за пределы одной строки. Так трудно читать.

Хотя это дает вам правильный вывод, я рекомендую ниже лучшие практики. ✅

df["FinalStatus"] = ''
df.loc[(df["Status"] == 'Delivered') |
       (df["Status"] == 'Shipped'),
       'FinalStatus'] = 'Completed'
df.loc[(df["Status"] == 'Not Delivered') |
       (df["Status"] == 'Not Shipped'),
       'FinalStatus'] = 'Not Completed'

Как правило, один вкладыш — плохой выбор, если вы хотите отфильтровать набор данных на основе нескольких условий. Довольно легко разделить код на несколько строк, чтобы улучшить его читаемость.

Лично я часто использую эту передовую практику, поскольку она дает вам больший контроль над кодом, и вы можете в любое время добавить дополнительные условия, если это необходимо. 🏆

Это все, что вам нужно знать о лямбда-функциях в Python!

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

Я использую Python для анализа данных уже более 4 лет и обнаружил, что лямбда-функции весьма полезны в определенных сценариях, как я упоминал здесь.

Хотите прочитать все истории на Medium?

💡 Рассмотрите вариант Стать участником Medium, чтобы получить неограниченный доступ к историям на Medium, написанным мной и миллионом других авторов!. Я получу небольшую часть вашего гонорара без дополнительных затрат для вас.

💡 Не забудьте Подписаться на мою рассылку, чтобы не пропустить новую статью о руководствах, хитростях и советах по науке о данных, SQL и Python.

Спасибо, что прочитали!