Как и многие новички или опытные разработчики Python, я часто ломаю голову над лямбда-функциями всякий раз, когда сталкиваюсь с ними, просто потому, что никогда не трачу мало времени на их понимание.
После того, как, наконец, надоело, что они являются не более чем источником путаницы, и потратил время на изучение того, как они работают, оказывается, что лямбда-функции не так уж и запутаны.
Итак… Что такое лямбда-функция?
В Python (и многих других языках) лямбда-функция — это просто анонимная функция, содержащая только одно выражение.
Простой пример — лямбда-функция, используемая для возведения x
в степень 2.
lambda x: x ** 2
Здесь у нас есть ключевое слово lambda
для обозначения того, что это лямбда-функция, за которым следует аргумент лямбда x
. Одиночное лямбда-выражение находится справа от двоеточия. Результатом выражения будет возвращаемое значение лямбда-функции.
Более практичный пример — передача лямбда-функции в качестве функции фильтрации во встроенную функцию filter()
.
# Create a list of all even numbers between 0-10. filtered = [n for n in filter(lambda x: x % 2 == 0, range(0,11))] print(filtered)
>>> [0, 2, 4, 6, 8, 10]
В этом примере лямбда-функция вызывается функцией filter
, которой она передается. Затем каждый элемент в итерируемом range(0,11)
передается в аргумент лямбда-выражения x
, лямбда-выражение оценивает, является ли число нечетным или четным, и соответственно возвращает true или false. Только значения, оцененные как истинные в лямбда-функции, затем включаются в результирующую итерацию, созданную функцией filter()
.
Тот же результат может быть достигнут с помощью обычной функции Python. Этот подход, несмотря на то, что он является более подробным, может быть предпочтительнее, так как он более четко показывает, каково именно предполагаемое поведение функций фильтра, и есть ли необходимость написать модульный тест для функции фильтра.
def filter_even(x): return x % 2 == 0
# Create a list of all even numbers between 0-10. filtered = [n for n in filter(filter_even, range(0,11))] print(filtered)
Представление?
Учитывая совершенно другой синтаксис по сравнению с обычным определением функции, можно было бы подумать, что среда выполнения Python выполняет лямбда-функции по-другому, что приводит к некоторому изменению производительности.
Это не так, как видно из приведенного ниже диассемблированного байт-кода Python, единственное отличие состоит в том, что стандартная функция Python имеет имя, в котором лямбда-функция называется просто lambda
.
print(dis("def filter_even(x): return x % 2 == 0"))
# Standard Python function bytecode Disassembly of <code object filter_even at 0x101b0bea0, file "<dis>", line 1>: 1 0 LOAD_FAST 0 (x) 2 LOAD_CONST 1 (2) 4 BINARY_MODULO 6 LOAD_CONST 2 (0) 8 COMPARE_OP 2 (==) 10 RETURN_VALUE
print(dis("lambda x: x % 2 == 0"))
# Lambda function bytecode Disassembly of <code object <lambda> at 0x10b59cd40, file "<dis>", line 1>: 1 0 LOAD_FAST 0 (x) 2 LOAD_CONST 1 (2) 4 BINARY_MODULO 6 LOAD_CONST 2 (0) 8 COMPARE_OP 2 (==) 10 RETURN_VALUE
Вывод
Основным преимуществом лямбда-функций является возможность определить одноразовую функцию с единой ответственностью, которую можно легко передать другим.
Однако есть несколько недостатков, связанных с ними.
- Незнакомый синтаксис.
- Не подлежит тестированию.
- Невозможно предоставить строку документации.
- Трудно понять трассировку из-за лямбда-функций, не имеющих определенного имени.
Поскольку недостатки в значительной степени перевешивают преимущества, я бы, вероятно, воздержался от лямбда-функций во всем, кроме простых функций, предоставляемых в качестве аргументов для таких функций, как sorted()
, map()
и filter()
.