Почему Python lambdas полезен?

Я пытаюсь выяснить Python lambdas. Является ли лямбда одним из тех "интересных" языковых предметов, которые в реальной жизни нужно забыть?

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

Это напоминает мне переполнение (переполнение буфера) типов C - указание на верхнюю переменную и перегрузку для установки других значений поля. Он чувствует себя как мастер-класс, но кошмар кодера поддержки.

Ответ 1

Вы говорите о лямбда-функциях? Как

lambda x: x**2 + 2*x - 5

Те вещи на самом деле весьма полезны. Python поддерживает стиль программирования, называемый функциональным программированием, где вы можете передавать функции другим функциям. Пример:

mult3 = filter(lambda x: x % 3 == 0, [1, 2, 3, 4, 5, 6, 7, 8, 9])

устанавливает mult3 в [3, 6, 9], те элементы исходного списка, которые кратные 3. Это короче (и, можно утверждать, яснее), чем

def filterfunc(x):
    return x % 3 == 0
mult3 = filter(filterfunc, [1, 2, 3, 4, 5, 6, 7, 8, 9])

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

mult3 = [x for x in [1, 2, 3, 4, 5, 6, 7, 8, 9] if x % 3 == 0]

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

  • Возврат функции из другой функции

    >>> def transform(n):
    ...     return lambda x: x + n
    ...
    >>> f = transform(3)
    >>> f(4)
    7
    

    Это часто используется для создания функциональных оболочек, таких как декораторы Python.

  • Объединение элементов итерируемой последовательности с reduce()

    >>> reduce(lambda a, b: '{}, {}'.format(a, b), [1, 2, 3, 4, 5, 6, 7, 8, 9])
    '1, 2, 3, 4, 5, 6, 7, 8, 9'
    
  • Сортировка по альтернативному ключу

    >>> sorted([1, 2, 3, 4, 5, 6, 7, 8, 9], key=lambda x: abs(5-x))
    [5, 4, 6, 3, 7, 2, 8, 1, 9]
    

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

Ответ 2

lambda - просто причудливый способ сказать function. Помимо его названия, в нем нет ничего скрытого, устрашающего или загадочного. Когда вы прочтете следующую строку, замените lambda на function в своем уме:

>>> f = lambda x: x + 1
>>> f(3)
4

Он просто определяет функцию x. Некоторые другие языки, например R, говорят это явно:

> f = function(x) { x + 1 }
> f(3)
4

Вы видите? Это одна из самых естественных вещей в программировании.

Ответ 3

Двухстрочное резюме:

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

Ответ 4

Лямбда является частью очень важного механизма абстракции, который имеет дело с функциями более высокого порядка. Чтобы получить правильное понимание его ценности, пожалуйста, смотрите уроки высокого качества из Абельсона и Суссмана и прочитайте книгу SICP

Это актуальные проблемы в современном бизнесе программного обеспечения и становятся все более популярными.

Ответ 5

Я сомневаюсь, что лямбда исчезнет. См. Сообщение Guido о том, что, наконец, отказавшись от попытки удалить его. Также см. контур конфликта.

Вы можете проверить этот пост за более подробной информацией о сделке, стоящей за функциональными возможностями Python: http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html

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

Мои собственные два цента: Редко лямбда стоит того, насколько ясно. Как правило, существует более четкое решение, которое не включает лямбда.

Ответ 6

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

for value in ["one","two","three"]:
    b = tk.Button(label=value, command=lambda arg=value: my_callback(arg))
    b.pack()

(Обратите внимание: хотя в этом вопросе конкретно задается вопрос о lambda, вы также можете использовать functools.partial, чтобы получить тот же тип результата )

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

Ответ 7

В Python lambda - это просто способ определения функций inline,

  a = lambda x: x + 1
распечатать a (1)
Код>

и..

  def a (x): return x + 1
распечатать a (1)
Код>

.. являются точной.

Нет ничего, что вы можете сделать с лямбдой, которую вы не можете сделать с регулярной функцией — в функциях Python есть объект, как и все остальное, и lambdas просто определяют функцию:

<Предварительно > <код → → a = lambda x: x + 1 → > введите) < type 'function' > Код >

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

Для абсолютно случайного примера из статьи "Python lambda сломан!" :

Чтобы узнать, как lambda сломан, попробуйте создать список функций fs = [f0,..., f9], где fi (n) = я + n, Первая попытка:

<Предварительно > <код → → fs = [(lambda n: я + n) для я в диапазоне (10)] → > фс [3] (4) 13 Код >

Я бы поспорил, даже если бы это сработало, это ужасно и "безотносительно", та же функциональность могла быть написана многими другими способами, например:

<Предварительно > <код → → n = 4 → > [i + n для я в диапазоне (10)] [4, 5, 6, 7, 8, 9, 10, 11, 12, 13] Код >

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

Обратите внимание, что мы можем использовать лямбда и все еще приводит следующим образом:

<Предварительно > <код → → fs = [(lambda n, я = i: я + n) для я в диапазоне (10)] → > фс [3] (4) 7 Код >

Edit:

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

  w = PyQt4.QtGui.QLineEdit()
w.textChanged.connect(событие lambda: dothing())
Код>

Просто выполнение w.textChanged.connect(dothing) вызовет метод dothing с дополнительным аргументом event и вызовет ошибку. Используя средства лямбда, мы можем аккуратно отбросить аргумент, не определяя функцию обертки.

Ответ 8

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

plural_rules = [
    lambda n: 'all',
    lambda n: 'singular' if n == 1 else 'plural',
    lambda n: 'singular' if 0 <= n <= 1 else 'plural',
    ...
]
# Call plural rule #1 with argument 4 to find out which sentence form to use.
plural_rule[1](4) # returns 'plural'

Если вам нужно будет определить функцию для всех тех, кого вы с ума сошли до конца. Также было бы неплохо с именами функций, такими как plural_rule_1, plural_rule_2 и т.д. И вам нужно будет eval() когда вы plural_rule_2 от идентификатора переменной функции.

Ответ 9

Практически все, что вы можете сделать с помощью lambda, вы можете сделать лучше с именованными функциями или выражениями списков и генераторов.

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

Ответ 10

Я использую Python в течение нескольких лет, и я никогда не сталкивался с ситуацией, когда мне нужна лямбда. Действительно, как говорится в tutorial, это просто для синтаксического сахара.

Ответ 11

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

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

Ответ 12

Лямбда-функция - это небюрократический способ создания функции.

Что это. Например, позвольте предположить, что у вас есть ваша основная функция, и вам нужны квадратные значения. Давайте посмотрим на традиционный способ и способ лямбда:

Традиционный способ:

def main():
...
...
y = square(some_number)
...
return something

def square(x):
    return x**2

Лямбда:

def main():
...
square = lambda x: x**2
y = square(some_number)
return something

См. разницу?

Лямбда-функции очень хорошо сочетаются с списками, такими как списки или карты. На самом деле, понимание списка - это "питонический" способ выразить себя, используя лямбду. Пример:

>>>a = [1,2,3,4]
>>>[x**2 for x in a]
[1,4,9,16]

Посмотрим, что означает каждый элемент синтаксиса:

[]: "Дайте мне список"

x ** 2: "используя эту новорожденную функцию"

для x в a: "в каждый элемент из a <

Это удобно? Создание таких функций. Позвольте переписать его, используя lambda:

>>> square = lambda x: x**2
>>> [square(s) for x in a]
[1,4,9,16]

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

(i) одна функция

(ii) итерируемый

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

Итак, используя карту, мы бы имели:

>>> a = [1,2,3,4]
>>> squared_list = map(lambda x: x**2, a)

Если вы освоите lambdas и картографирование, у вас будет большая сила для манипулирования данными и кратким образом. Лямбда-функции не являются ни скрытыми, ни убирают ясность кода. Не путайте что-то новое с чем-то новым. Когда вы начнете использовать их, вы найдете это очень понятным.

Ответ 13

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

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

log_timestamp(datetime.datetime.now() - datetime.timedelta(minutes = 30))

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

log_timestamp(lambda : datetime.datetime.now() - datetime.timedelta(minutes = 30))

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

Конечно, есть альтернативные способы сделать это (например, с помощью модуля operator), но я надеюсь, что я передал этот вопрос.

Обновление: Здесь - чуть более конкретный пример реального мира.

Обновление 2: Я думаю, что это пример того, что называется thunk.

Ответ 14

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

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

В основном это сводится к нескольким точкам:

  • легче читать программное обеспечение, которое явно написано с использованием значимых имен. У анонимных закрытий по определению не может быть значимого имени, так как у них нет имени. По-видимому, эта краткость по какой-то причине также заражает лямбда-параметры, поэтому мы часто видим такие примеры, как lambda x: x + 1
  • проще повторно использовать именованные блокировки, так как их можно называть по имени более одного раза, когда есть имя для ссылки на них.
  • легче отлаживать код, который использует именованные закрытия вместо lambdas, потому что имя будет отображаться в tracebacks и вокруг ошибки.

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

Первое недовольство - это просто другое ненужное ключевое слово, загромождающее язык.

Второе недовольство глубже и на уровне парадигмы, т.е. мне не нравится, что они продвигают стиль функционального программирования, потому что этот стиль менее гибкий, чем процесс передачи сообщений, объектно-ориентированный или процедурный стили, поскольку исчисление лямбда а не Turing-complete (к счастью в Python, мы все еще можем выйти из этого ограничения даже внутри лямбда). Причины, по которым я чувствую, что лямбды продвигают этот стиль:

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

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

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

Ответ 15

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

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

squared = map(lambda x: x*x, [1, 2, 3, 4, 5])

Вышеприведенная строка кода возвращает список квадратов номеров в списке. Конечно, вы также можете сделать это как:

def square(x):
    return x*x

squared = map(square, [1, 2, 3, 4, 5])

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

Кроме того, как отметил в своем ответе @David Zaslavsky, в списках понимания не всегда есть путь, особенно если ваш список должен получать значения из некоторого неясного математического пути.

С более практической точки зрения, одно из самых больших преимуществ lambdas для меня в последнее время было в графическом интерфейсе и программировании, основанном на событиях. Если вы посмотрите на обратные вызовы в Tkinter, все, что они принимают в качестве аргументов, - это событие, вызвавшее их. Например.

def define_bindings(widget):
    widget.bind("<Button-1>", do-something-cool)

def do-something-cool(event):
    #Your code to execute on the event trigger

Теперь, если у вас есть какие-то аргументы? Нечто простое, как передача 2 аргументов для хранения координат щелчка мыши. Вы можете сделать это следующим образом:

def main():
    # define widgets and other imp stuff
    x, y = None, None
    widget.bind("<Button-1>", lambda event: do-something-cool(x, y))

def do-something-cool(event, x, y):
    x = event.x
    y = event.y
    #Do other cool stuff

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

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

Ответ 16

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

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

Ответ 17

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

Вам просто нужно думать немного иначе. Я уверен, что скоро вам это понравится. Но будьте осторожны, если вы имеете дело только с python. Поскольку лямбда не является реальным закрытием, она как-то "сломана": pythons lambda не работает

Ответ 18

Я только начинаю Python и сначала бегу головой в Лямбду, и мне понадобилось некоторое время, чтобы понять.

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

Является ли лямбда одним из этих "интересных" языковых предметов, которые в реальной жизни должны быть забыты?

Нет.

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

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

потенциал его переопределения в будущих выпусках (мое предположение основано на различных его определениях)

Я не видел серьезных предложений по переопределению его в Python, помимо исправления семантики закрытия несколько лет назад.

и уменьшенную четкость кодирования - следует ли ее избегать?

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

Это напоминает мне переполнение (переполнение буфера) типов C - указание на верхнюю переменную и перегрузку для установки других значений поля... своего рода техничное мастерство, но кошмар кодера обслуживания.

Лямбда подобна переполнению буфера? Вау. Я не могу представить, как вы используете лямбда, если считаете это "кошмаром обслуживания".

Ответ 19

Я начал читать книгу Дэвида Мерца "Обработка текстов на Python". Хотя у него есть довольно краткое описание Лямбды, примеры из первой главы в сочетании с объяснением в Приложении А заставили их спрыгнуть со страницы для меня (наконец), и я внезапно понял их ценность. Это не означает, что его объяснение будет работать для вас, и я все еще на стадии обнаружения, поэтому я не буду пытаться добавлять к этим ответам, кроме следующего: Я новичок в Python Я новичок в ООП Лямбдас был для меня борьбой Теперь, когда я читаю Mertz, я думаю, что получаю их, и я считаю их очень полезными, поскольку я думаю, что они позволяют более чистый подход к программированию.

Он воспроизводит Zen Python, одна строка которого Простой лучше, чем сложный. Как программист, не являющийся OOP, читающий код с lambdas (и до тех пор, пока списки на прошлой неделе) Это просто?. Сегодня я, наконец, понял, что на самом деле эти функции делают код более читабельным и понятным, чем альтернатива - это всегда какой-то цикл. Я также понял, что, как и финансовые отчеты, Python не предназначен для новичков, а предназначен для пользователя, который хочет получить образование. Я не могу поверить, насколько мощный этот язык. Когда мне стало ясно (цель) и ценность лямбда, я хотел разорвать около 30 программ и начать с того, чтобы поместиться в лямбда, где это необходимо.

Ответ 20

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

print 'hi there'

Тогда нечего делать. Но что, если мне нужен мой выбор, чтобы иметь конкретную деталь. Например, если я выбираю выбор A, он вызывает функцию, которая принимает некоторый аргумент, который зависит от выбора A, B или C, TKinter не может этого поддерживать. Ламда был единственным вариантом обойти это на самом деле...

Ответ 21

Полезным случаем для использования lambdas является улучшить читаемость понятий длинного списка. В этом примере loop_dic является кратким для ясности, но представьте loop_dic очень долго. Если вы просто используете простое значение, которое включает i вместо лямбда-версии этого значения, вы получите NameError.

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> loop_dic = lambda i: {"name": i["name"] + " Wallace" }
>>> new_lis = [loop_dic(i) for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]

Вместо

>>> lis = [{"name": "Peter"}, {"name": "Josef"}]

>>> new_lis = [{"name": i["name"] + " Wallace"} for i in lis]

>>> new_lis
[{'name': 'Peter Wallace'}, {'name': 'Josef Wallace'}]

Ответ 22

Я использую lambdas, чтобы избежать дублирования кода. Это сделает функцию легко понятной Например:

def a_func()
  ...
  if some_conditon:
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)
  else
     ...
     call_some_big_func(arg1, arg2, arg3, arg4...)

Я заменяю это темпом lambda

def a_func()
  ...
  call_big_f = lambda args_that_change: call_some_big_func(arg1, arg2, arg3, args_that_change)
  if some_conditon:
     ...
     call_big_f(argX)
  else
     ...
     call_big_f(argY)

Ответ 23

Я начинающий питон, поэтому, чтобы получить ясное представление о лямбда, я сравнил его с циклом 'for'; с точки зрения эффективности. Здесь код (python 2.7) -

import time
start = time.time() # Measure the time taken for execution

def first():
    squares = map(lambda x: x**2, range(10))
    # ^ Lambda
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0 seconds

def second():
    lst = []
    for i in range(10):
        lst.append(i**2)
    # ^ a 'for' loop
    end = time.time()
    elapsed = end - start
    print elapsed + ' seconds'
    return elapsed # gives 0.0019998550415 seconds.

print abs(second() - first()) # Gives 0.0019998550415 seconds!(duh)

Ответ 24

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

Вот примеры:

для реализации шаблона нулевого объекта:

{
    DATA_PACKET: self.handle_data_packets
    NET_PACKET: self.handle_hardware_packets
}.get(packet_type, lambda x : None)(payload)

для привязки параметра:

скажем, что у меня есть следующий API

def dump_hex(file, var)
    # some code
    pass

class X(object):
    #...
    def packet_received(data):
        # some kind of preprocessing
        self.callback(data)
    #...

Затем, когда я не буду быстро удалять полученные данные в файл, я делаю это:

dump_file = file('hex_dump.txt','w')
X.callback = lambda (x): dump_hex(dump_file, x)
...
dump_file.close()

Ответ 25

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

Например:

import imported.module

def func():
    return lambda: imported.module.method("foo", "bar")

в отличие от:

import imported.module

def func():
    def cb():
        return imported.module.method("foo", "bar")
    return cb

Ответ 26

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