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




map list (22)

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

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

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

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

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


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

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

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

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


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

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


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

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

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

С более практической точки зрения, одно из самых больших преимуществ 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 - это не то же самое, что и lambdas LISP (которые более мощные), но вы действительно можете делать с ними много волшебных вещей.


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

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

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


Полезным случаем использования lambdas является улучшение удобочитаемости для понимания длинного списка . В этом примере loop_dicкоротко для ясности, но представьте, loop_dicчто он очень длинный. Если вы просто используете простое значение, которое включает iвместо лямбда-версии этого значения, вы получите a 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'}]

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

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

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

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

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


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

Вот примеры:

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

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

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

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


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

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

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

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)

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


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


Одна из приятных вещей о 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 .


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


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

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


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

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


В 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 и вызовет ошибку. Используя лямбда-средства, мы можем аккуратно отказаться от аргумента, не определяя функцию обертывания.


Я нахожу лямбда полезной для списка функций, которые делают то же самое, но для разных обстоятельств. Подобно правилам множественного числа 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 от идентификатора переменной функции.


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

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]
    

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


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

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

print 'hi there'

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


Существует также Plumbum

>>> from plumbum import local
>>> ls = local["ls"]
>>> ls
LocalCommand(<LocalPath /bin/ls>)
>>> ls()
u'build.py\ndist\ndocs\nLICENSE\nplumbum\nREADME.rst\nsetup.py\ntests\ntodo.txt\n'
>>> notepad = local["c:\\windows\\notepad.exe"]
>>> notepad()                                   # Notepad window pops up
u''                                             # Notepad window is closed by user, command returns






python function lambda closures