В языках программирования существует понятие "объекты первого рода (или класса)". Им обозначают элементы, которые могут быть переданы в функции, возвращены из функций и присвоены переменным. К таким элементам относятся любые данные, например числа, строки, массивы или логические значения.
# 5 — число, объект первого рода (сохранено в переменной)
num = 5
# 2 — число, объект первого рода (аргумент функции)
# содержимое num — объект первого рода (аргумент функции)
# содержимое result — объект первого рода (возвращаемое значение)
result = pow(num, 2)
Объектами первого рода может быть не только то, что мы привыкли именовать словом "данные", но и любая конструкция языка, например, функции. В Python функции — это объекты первого рода. Такая особенность очень серьезно влияет не только на обращение с функциями, но и на общий стиль программирования. Ниже мы поговорим об обращении с функциями как с данными.
Анонимные функции
Анонимные функции — это функции, у которых нет имени. Они определяются с помощью ключевого слова lambda
. Это ключевое слово названо в честь лямбда-абстракции — основы Лямбда Исчисления. Это математический аппарат, который часто применяется в разработке языков программирования. В Лямбда Исчислении все функции — анонимные. Поэтому анонимные функции во многих языках тоже иногда называют лямбдами или лямбда-функциями.
lambda x: x + 2
В примере выше мы создали лямбда-функцию с параметром x
, которая прибавляет к переданному значению 2. Как мы упомянули выше, функции в Python объекты первого рода, а значит мы можем присвоить функцию переменной.
add_two = lambda x: x + 2
Теперь работа с ней не отличается от работы с привычными нам функциями
add_two(1) # 3
add_two(5) # 7
Даже сохранив функцию внутри переменной, ничего не мешает передать ее в другую переменную. Только не забывайте об объектной природе функции. В другую переменную передается не сама функция, а ссылка на нее:
# так выглядит простейшая лямбда без параметров
a = lambda: 'I love Hexlet'
a() # 'I love Hexlet'
b = a
b() # 'I love Hexlet'
Более того, любую функцию можно использовать напрямую, без сохранения в переменной:
(lambda: print('I love Hexlet'))() # => I love Hexlet
Имя переменной – это лишь её имя, а сама функция не имеет имени. Поэтому такие функции в программировании и называют "анонимными".
В примере мы сделали вызов функции, что называется, "на лету": сначала создали (lambda: print('I love Hexlet'))
и сразу же сделали вызов с помощью оператора вызова функции ()
. При этом определение функции следует обернуть в круглые скобки, чтобы обозначить границы определения для интерпретатора, которому нужно "понимать", что конкретно вы хотите вызвать. Понятно, что после такого выражения доступ к функции будет утерян, потому что она нигде не была сохранена.
У синтаксиса лямбда-функций есть несколько особенностей:
- Параметры анонимных функций не заключены в скобки. Но все средства для описания параметров доступны в полной мере — и именованные параметры, и
*args
с**kwargs
- Тело лямбда-функции — это всегда одно выражение, результат вычисления которого и будет возвращаемым значением. В теле лямбда-функции не получится выполнить несколько действий и не получится использовать многострочные конструкции вроде
for
иwhile
. Но зато анонимные функции обычно просто читать, чего было бы сложно добиться, разреши авторам "многострочные" лямбды - Лямбды не используют
return
- объявление функции является выражением.
Именованные функции
Вернемся к примеру выше:
add_two = lambda x: x + 2
add_two(1) # 3
Можно заметить, что конструкция add_two = lambda x
похожа на знакомое нам объявление def add_two(x):
. Действительно, ключевое слово def
лишь связывает определение функции с именем переменной. Потому такие функции называют именованными в противоположность анонимным. При этом все свойства функции как объекта первого рода сохраняются.
def add_two(x):
return x + 2
# add_two - функция, объект первого рода (сохранено в переменной)
a = add_two
a(1) # 3
Создание внутри другой функции
Раз лямбда-функция — выражение, мы можем определять её в любом месте программы, допускающем использование выражений, например, в теле другой функции:
def sum(a, b):
# определили "внутреннюю" анонимную функцию и
# сохранили в inner_sum
inner_sum = lambda x, y: x + y
# вызвали внутреннюю функцию и
# вернули результат вызова наружу из sum
return inner_sum(a, b)
sum(1, 4) # 5
Из свойств функций как объектов первого рода мы рассмотрели пока присваивание переменной. В дальнейших уроках мы рассмотрим как можно передавать функции в другие функции в качестве аргументов и возвращать из других функций. Использование функций как значения значительно повышает выразительные возможности языка, и в этом вы скоро убедитесь.
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.