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




python lambda map function example (18)

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

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

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

Нет.

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

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

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

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

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

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

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

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

https://code.i-harness.com

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

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

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


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

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


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 чтобы получить тот же тип результата)

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


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

a = lambda x: x + 1
print a(1)

а также..

def a(x): return x + 1
print a(1)

.. то же самое.

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

>>> a = lambda x: x + 1
>>> type(a)
<type 'function'>

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

Для совершенно случайного примера из статьи «Лямбда Питона сломана!» :

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

>>> fs = [(lambda n: i + n) for i in range(10)]
>>> fs[3](4)
13

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

>>> n = 4
>>> [i + n for i in range(10)]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

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

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

>>> fs = [(lambda n,i=i: i + n) for i in range(10)]
>>> fs[3](4)
7

Редактировать:

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

w = PyQt4.QtGui.QLineEdit()
w.textChanged.connect(lambda event: dothing())

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


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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

Обновление : Here немного более конкретный пример реального мира.

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


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

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


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


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

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

Я заменяю это темной лямбдой

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)

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

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


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

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

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

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


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

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

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

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"

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

>>> 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)

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


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


Я использую 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

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

Вот примеры:

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

{
    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()

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

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


Я начинающий питон, поэтому, чтобы получить ясное представление о лямбда, я сравнил его с циклом «для»; с точки зрения эффективности. Вот код (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)




closures