Зарегистрируйтесь, чтобы продолжить обучение

Объекты первого класса Python: Функции

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

# 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

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


Дополнительные материалы

  1. Документация

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

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

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

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

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
Программирование на Python, Разработка веб-приложений и сервисов используя Django, проектирование и реализация REST API
10 месяцев
с нуля
Старт 26 декабря

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»