Сообщить об ошибке.

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]
    
  • c ключевыми функциями (функции принимают ключ в качестве параметра). Ключ может быть лямбда-выражением.

    # Сортировка словаря
    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)]
    
  • в качестве списка lambda-выражений. В результате получается список действий, выполняемых по требованию:

    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)
    
  • в качестве словаря, содержащего lambda-функции:

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